<?php

namespace App\Http\Controllers;

use App\Exports\BookingExport;
use Illuminate\Http\Request;
use App\Models\Booking;
use App\Models\Coupon;
use App\Models\Service;
use App\Models\Payment;
use App\Models\User;
use App\Models\BookingStatus;
use App\Models\PostJobRequest;
use App\Models\ProviderAddressMapping;
use App\Http\Requests\BookingUpdateRequest;
use App\Models\Notification;
use Yajra\DataTables\DataTables;
use PDF;
use App\Models\AppSetting;
use Carbon\Carbon;
use App\Traits\NotificationTrait;
use App\Traits\EarningTrait;

use App\Models\ServiceAddon;
use App\Models\BookingRating;
use App\Models\Setting;
use App\Models\Country;
use Maatwebsite\Excel\Facades\Excel;
use App\Models\PaymentGateway;

class BookingController extends Controller
{
    use NotificationTrait;
    use EarningTrait;
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Request $request)
    {
        $filter = [
            'status' => $request->status,
        ];
        $pageTitle = __('messages.bookings');
        $auth_user = authSession();
        $authRole = $auth_user->roles->pluck('name')->first();
        $assets = ['datatable'];

        $provider_id = '';
        $handyman_id = '';
        $customer_id = '';

        // Calculate total earnings based on role
        $advanceFilter = [];
        $paymentStatus = ['paid', 'pending','advanced_paid','Advanced Refund'];
        $paymentType = PaymentGateway::where('status',1)->get()->pluck('title', 'type')->put('wallet', 'Wallet');
        $bookingStatus = BookingStatus::where('status', 1)->orderBy('sequence', 'ASC')->get()->pluck('label', 'value');
        switch ($authRole) {
            case 'admin':
                $totalEarning = Booking::where('status', '!=', 'cancelled')
                ->whereHas('handymanAdded', function ($query) {
                    $query->whereNotNull('provider_id'); // Ensure handyman is not null
                })
                ->sum('total_amount');
                break;
            case 'demo_admin':
                $totalEarning = Booking::where('status', '!=', 'cancelled')
                                 ->whereHas('handymanAdded', function ($query) {
                                     $query->whereNotNull('provider_id'); // Ensure handyman is not null
                                 })
                                 ->sum('total_amount');
                break;


            case 'provider':
                $totalEarning = Booking::where('status','!=' ,'cancelled')->whereHas('handymanAdded', function ($query) use ($auth_user) {
                    $query->where('provider_id', $auth_user->id);
                })->sum('total_amount');
            break;


            case 'handyman':
                $totalEarning = Booking::where('status','!=' ,'cancelled')->whereHas('handymanAdded', function ($query) use ($auth_user) {
                    $query->where('handyman_id', $auth_user->id);
                })->sum('total_amount');
                break;

            default:
                $totalEarning = 0;
                break;
        }

        $advanceFilter = [
            'paymentStatus' => ['paid', 'pending', 'advanced_paid', 'Advanced Refund'],
            'paymentType' => PaymentGateway::where('status', 1)->get()->pluck('title', 'type')->put('wallet', 'Wallet'),
            'bookingStatus' => BookingStatus::where('status', 1)->orderBy('sequence', 'ASC')->get()->pluck('label', 'value')
        ];

        return view('booking.index', compact('pageTitle', 'auth_user', 'assets', 'filter', 'customer_id', 'provider_id', 'handyman_id', 'advanceFilter', 'totalEarning'));
    }


    public function index_data(DataTables $datatable, Request $request)
    {
        $auth_user = authSession();
        $query = Booking::query()->myBooking()->with('payment', 'commissionsdata', 'handymanAdded');

        // Apply role-based filters
        if ($auth_user->hasRole('handyman')) {
            $query->whereHas('handymanAdded', function($q) use ($auth_user) {
                $q->where('handyman_id', $auth_user->id);
            });
        }

        $filter = $request->filter;

        if (isset($filter)) {
            if (isset($filter['column_status'])) {
                $query->where('status', $filter['column_status']);
            }
            if (isset($filter['status'])) {
                $query->where('status', $filter['status']);
            }
        }

        // Handle advanceFilter
        $advanceFilter = $request->advanceFilter;

        if (isset($advanceFilter)) {
            // Date range filter - Updated logic
            if (!empty($advanceFilter['date_range'])) {
                $dates = explode(' to ', $advanceFilter['date_range']);
                if (count($dates) === 2) {
                    $startDate = date('Y-m-d', strtotime($dates[0]));
                    $endDate = date('Y-m-d', strtotime($dates[1]));
                    $query->whereDate('date', '>=', $startDate)
                          ->whereDate('date', '<=', $endDate);
                } elseif (count($dates) === 1) {
                    $date = date('Y-m-d', strtotime($dates[0]));
                    $query->whereDate('date', $date);
                }
            }

            // Other filters...
            $filters = [
                'customer_id' => 'customer_id',
                'provider_id' => 'provider_id',
                'service_id' => 'service_id',
                'handyman_id' => ['handymanAdded', 'handyman_id'],
                'booking_status' => 'status',
                'payment_status' => ['payment', 'payment_status'],
                'payment_type' => ['payment', 'payment_type'],
            ];

            foreach ($filters as $key => $filter) {
                if (!empty($advanceFilter[$key])) {
                    if (is_array($advanceFilter[$key])) {
                        if (is_array($filter)) {
                            $query->whereHas($filter[0], function ($subQuery) use ($filter, $advanceFilter, $key) {
                                $subQuery->whereIn($filter[1], $advanceFilter[$key]);
                            });
                        } else {
                            $query->whereIn($filter, $advanceFilter[$key]);
                        }
                    } else {
                        $query->where($filter, $advanceFilter[$key]);
                    }
                }
            }
        }

        if (auth()->user()->hasAnyRole(['admin'])) {
            $query->withTrashed();
        }

        return $datatable->eloquent($query)
            // ->addColumn('check', function ($row) {
            //     return '<input type="checkbox" class="form-check-input select-table-row"  id="datatable-row-' . $row->id . '"  name="datatable_ids[]" value="' . $row->id . '" data-type="booking" onclick="dataTableRowCheck(' . $row->id . ',this)">';
            // })
            ->editColumn('id', function ($query) {
                return "<a class='btn-link btn-link-hover' href=" . route('booking.show', $query->id) . ">#" . $query->id . "</a>";
            })
            ->editColumn('customer_id', function ($query) {
                return view('booking.customer', compact('query'));
            })
            ->filterColumn('customer_id', function ($query, $keyword) {
                $query->whereHas('customer', function ($q) use ($keyword) {
                    $q->where('display_name', 'like', '%' . $keyword . '%');
                });
            })
            ->orderColumn('customer_id', function ($query, $order) {
                $query->select('bookings.*')
                    ->join('users as customers', 'customers.id', '=', 'bookings.customer_id')
                    ->orderBy('customers.display_name', $order);
            })
            ->editColumn('service_id', function ($query) {
                if (!empty($query->bookingPackage)) {
                    $name = optional($query->bookingPackage)->name;
                } else {
                    $name = optional($query->service)->name;
                }
                $service_name = ($query->service_id != null && isset($query->service)) ? $name : "";
                return "<a class='btn-link btn-link-hover' href=" . route('booking.show', $query->id) . ">" . $service_name . "</a>";
            })
            ->filterColumn('service_id', function ($query, $keyword) {
                $query->whereHas('service', function ($q) use ($keyword) {
                    $q->where('name', 'like', '%' . $keyword . '%');
                });
            })
            ->orderColumn('service_id', function ($query, $order) {
                $query->join('services', 'services.id', '=', 'bookings.service_id')
                    ->orderBy('services.name', $order);
            })
            ->editColumn('date', function ($query) {
                $sitesetup = Setting::where('type', 'site-setup')->where('key', 'site-setup')->first();
                $datetime = $sitesetup ? json_decode($sitesetup->value) : null;

                $date = optional($datetime)->date_format && optional($datetime)->time_format
                    ? date(optional($datetime)->date_format, strtotime($query->date)) . '  ' . date(optional($datetime)->time_format, strtotime($query->date))
                    : $query->date;

                return $date;
            })
            ->editColumn('provider_id', function ($query) {
                return view('booking.provider', compact('query'));
            })
            ->filterColumn('provider_id', function ($query, $keyword) {
                $query->whereHas('provider', function ($q) use ($keyword) {
                    $q->where('display_name', 'like', '%' . $keyword . '%');
                });
            })
            ->orderColumn('provider_id', function ($query, $order) {
                $query->select('bookings.*')
                    ->join('users as providers', 'providers.id', '=', 'bookings.provider_id')
                    ->orderBy('providers.display_name', $order);
            })
            ->editColumn('status', function ($query) {
                return bookingstatus(BookingStatus::bookingStatus($query->status));
            })
            ->editColumn('payment_id', function ($query) {
                $payment = $query->payment()->orderBy('id', 'desc')->first();
                $payment_status = $payment ? $payment->payment_status : null;
                if ($payment_status !== null) {
                    $status = '<span class="text-center text-white badge bg-primary">' . str_replace('_', " ", ucfirst($payment_status)) . '</span>';
                } else {
                    $status = '<span class="badge text-primary bg-primary-subtle">' . __('messages.pending') . '</span>';
                }
                return $status;
            })
            ->filterColumn('payment_id', function ($query, $keyword) {
                $query->whereHas('payment', function ($q) use ($keyword) {
                    $q->where('payment_status', 'like', $keyword . '%');
                });
            })
            ->editColumn('total_amount', function ($query) {
                return $query->total_amount ? getPriceFormat($query->total_amount) : '-';
            })

            ->addColumn('action', function ($booking) {
                return view('booking.action', compact('booking'))->render();
            })

            ->editColumn('updated_at', function ($query) {
                $diff = Carbon::now()->diffInHours($query->updated_at);
                if ($diff < 25) {
                    return $query->updated_at->diffForHumans();
                } else {
                    return $query->updated_at->isoFormat('llll');
                }
            })
            ->addIndexColumn()
            ->rawColumns(['action', 'status', 'payment_id', 'service_id', 'id'])
            ->toJson();
    }


    public function export(Request $request)
    {
        // Get the selected format (default to 'xlsx')
        $format = $request->input('format', 'xlsx');

        // Validate format
        $validFormats = ['xlsx', 'xls', 'ods', 'csv', 'pdf', 'html'];
        if (!in_array($format, $validFormats)) {
            return response()->json(['error' => 'Invalid format selected.'], 400);
        }

        // Get the selected columns (passed as JSON array)
        $columns = json_decode($request->input('columns'), true);

        // Create a new instance of BookingExport with role-based filtering
        $auth_user = authSession();

        // Modify the query based on user role
        $query = Booking::query()->with(['service', 'customer', 'provider', 'payment', 'handymanAdded']);

        // Apply role-based filters
        switch ($auth_user->roles->pluck('name')->first()) {
            case 'handyman':
                $query->whereHas('handymanAdded', function($q) use ($auth_user) {
                    $q->where('handyman_id', $auth_user->id);
                });
                break;

            case 'provider':
                $query->where('provider_id', $auth_user->id);
                break;

            case 'user':
                $query->where('customer_id', $auth_user->id);
                break;
        }

        // Apply any additional filters from the request
        if ($request->has('advanceFilter')) {
            $advanceFilter = $request->advanceFilter;

            // Apply filters similar to index_data method
            if (!empty($advanceFilter['customer_id'])) {
                $query->whereIn('customer_id', $advanceFilter['customer_id']);
            }
            if (!empty($advanceFilter['service_id'])) {
                $query->whereIn('service_id', $advanceFilter['service_id']);
            }
            if (!empty($advanceFilter['booking_status'])) {
                $query->whereIn('status', $advanceFilter['booking_status']);
            }
            if (!empty($advanceFilter['payment_status'])) {
                $query->whereHas('payment', function($q) use ($advanceFilter) {
                    $q->whereIn('payment_status', $advanceFilter['payment_status']);
                });
            }
            if (!empty($advanceFilter['payment_type'])) {
                $query->whereHas('payment', function($q) use ($advanceFilter) {
                    $q->whereIn('payment_type', $advanceFilter['payment_type']);
                });
            }
            if (!empty($advanceFilter['date_range'])) {
                $dates = explode(' to ', $advanceFilter['date_range']);
                if (count($dates) === 2) {
                    $query->whereDate('date', '>=', $dates[0])
                          ->whereDate('date', '<=', $dates[1]);
                } elseif (count($dates) === 1) {
                    $query->whereDate('date', $dates[0]);
                }
            }
        }

        // Check if there's any data to export
        $bookingData = $query->get();
        if ($bookingData->isEmpty()) {
            return response()->json(['error' => 'No data found for export.'], 404);
        }

        // Create BookingExport instance with the filtered query
        $bookingExport = new BookingExport($columns, $query);

        // Set the filename based on the selected format
        $filename = 'bookings.' . $format;

        // Handle PDF format specifically
        if ($format === 'pdf') {
            return Excel::download($bookingExport, $filename, \Maatwebsite\Excel\Excel::DOMPDF);
        }

        // Handle other formats (xlsx, xls, ods, csv, html)
        return Excel::download($bookingExport, $filename, constant('\Maatwebsite\Excel\Excel::' . strtoupper($format)));
    }

    /* bulck action method */
    public function bulk_action(Request $request)
    {
        $ids = explode(',', $request->rowIds);

        $actionType = $request->action_type;

        $message = 'Bulk Action Updated';
        switch ($actionType) {
            case 'change-status':
                $branches = Booking::whereIn('id', $ids)->update(['status' => $request->status]);
                $message = 'Bulk Booking Status Updated';
                break;

            case 'delete':
                $bookings = Booking::whereIn('id', $ids)->get();
                foreach ($bookings as $booking) {
                    $booking->delete();
                }

                $message = 'Bulk Booking Deleted';
                break;

            case 'restore':
                $bookings = Booking::withTrashed()->whereIn('id', $ids)->get();
                foreach ($bookings as $booking) {
                    $booking->restore();
                }
                $message = 'Bulk Booking Restored';
                break;

            case 'permanently-delete':
                $bookings = Booking::withTrashed()->whereIn('id', $ids)->get();
                foreach ($bookings as $booking) {
                    $booking->forceDelete();
                }
                $message = 'Bulk Booking Permanently Deleted';
                break;

            default:
                return response()->json(['status' => false, 'message' => 'Action Invalid']);
                break;
        }

        return response()->json(['status' => true, 'message' => $message]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create(Request $request)
    {
        $id = $request->id;
        $auth_user = authSession();

        $bookingdata = Booking::find($id);
        $pageTitle = __('messages.update_form_title', ['form' => __('messages.booking')]);

        if ($bookingdata == null) {
            $pageTitle = __('messages.add_button_form', ['form' => __('messages.booking')]);
            $bookingdata = new Booking;
        }

        return view('booking.create', compact('pageTitle', 'bookingdata', 'auth_user'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $sitesetup = Setting::where('type', 'site-setup')->where('key', 'site-setup')->first();
        $admin = json_decode($sitesetup->value);
        date_default_timezone_set($admin->time_zone ?? 'UTC');
        $data = $request->all();

        $data['tax'] = null;

        if ($request->id == null) {
            $data['status'] = !empty($data['status']) ? $data['status'] : 'pending';
        }

        if (isset($data['booking_slot'])) {
            $date = isset($request->date) ? date('Y-m-d', strtotime($request->date)) : date('Y-m-d');
            $time = date('H:i:s', strtotime($data['booking_slot']));
            $data['date'] = $date . ' ' . $time;
        } else {
            $data['date'] = isset($request->date) ? date('Y-m-d H:i:s', strtotime($request->date)) : date('Y-m-d H:i:s');
        }
        $service_data = Service::find($data['service_id']);

        $data['provider_id'] = !empty($data['provider_id']) ? $data['provider_id'] : $service_data->provider_id;

        if ($request->has('tax') && $request->tax != null) {
            $data['tax'] = json_encode($request->tax);
        }

        if ($request->coupon_id != null) {
            $coupons = Coupon::with('serviceAdded')->where('code', $request->coupon_id)
                ->where('expire_date', '>', date('Y-m-d H:i'))->where('status', 1)
                ->whereHas('serviceAdded', function ($coupon) use ($service_data) {
                    $coupon->where('service_id', $service_data->id);
                })->first();
            if ($coupons == null) {
                return comman_message_response(__('messages.invalid_coupon_code'), 406);
            } else {
                $data['coupon_id'] = $coupons->id;
            }
        }

        $user = User::where('id', $data['provider_id'])->with('providertype')->first();

        $result = Booking::updateOrCreate(['id' => $request->id], $data);

        $activity_data = [
            'activity_type' => 'add_booking',
            'booking_id' => $result->id,
            'booking' => $result,
        ];
        $this->sendNotification($activity_data);


        if ($data['coupon_id'] != null) {
            $coupons = Coupon::find($data['coupon_id']);

            $coupon_data = [
                'booking_id' => $result->id,
                'code' => $coupons->code,
                'discount' => $coupons->discount,
                'discount_type' => $coupons->discount_type,
            ];

            $result->couponAdded()->create($coupon_data);
        }
        if ($request->has('booking_address_id') && $request->booking_address_id != null) {
            $booking_address_mapping = ProviderAddressMapping::find($data['booking_address_id']);

            $booking_address_data = [
                'booking_id' => $result->id,
                'address' => $booking_address_mapping->address,
                'latitude' => $booking_address_mapping->latitude,
                'longitude' => $booking_address_mapping->longitude,
            ];

            $result->addressAdded()->create($booking_address_data);
        }

        if ($request->has('service_addon_id') && is_array($request->service_addon_id) != null) {
            foreach ($request->service_addon_id as $serviceaddon) {
                $booking_serviceaddon_mapping = ServiceAddon::find($serviceaddon);
                if ($booking_serviceaddon_mapping) {
                    $booking_serviceaddon_data = [
                        'booking_id' => $result->id,
                        'service_addon_id' => $booking_serviceaddon_mapping->id,
                        'name' => $booking_serviceaddon_mapping->name,
                        'price' => $booking_serviceaddon_mapping->price,
                    ];

                    $result->bookingAddonService()->create($booking_serviceaddon_data);
                }
            }
        }


        if ($request->has('booking_package') && $request->booking_package != null) {
            $booking_package = [
                'booking_id' => $result->id,
                'service_package_id' => $data['booking_package']['id'],
                'provider_id' => $data['provider_id'],
                'name' => $data['booking_package']['name'],
                'is_featured' => $data['booking_package']['is_featured'],
                'package_type' => $data['booking_package']['package_type'],
                'price' => $data['booking_package']['price'],
            ];
            if (!empty($data['booking_package']['start_at'])) {
                $booking_package['start_at'] = $data['booking_package']['start_at'];
            }
            if (!empty($data['booking_package']['end_at'])) {
                $booking_package['end_at'] = $data['booking_package']['end_at'];
            }
            if (!empty($data['booking_package']['subcategory_id'])) {
                $booking_package['subcategory_id'] = $data['booking_package']['subcategory_id'];
            }
            if (!empty($data['booking_package']['category_id'])) {
                $booking_package['category_id'] = $data['booking_package']['category_id'];
            }
            if (!empty($data['booking_package']['service_id'])) {

                $serviceIds = explode(',', $data['booking_package']['service_id']);

                $services = [];

                foreach ($serviceIds as $serviceId) {
                    $service = Service::find($serviceId);

                    if ($service) {
                        $services[] = [
                            'service_id' => $service->id,
                            'price' => $service->price,
                        ];
                    }
                }

                $booking_package['services'] = json_encode($services);
            }
            $result->bookingPackage()->create($booking_package);
        }
        if (!empty($data['type']) && $data['type'] === 'user_post_job') {
            $post_request = PostJobRequest::where('id', $data['post_request_id'])->first();
            $post_request->date = isset($request->date) ? date('Y-m-d H:i:s', strtotime($request->date)) : date('Y-m-d H:i:s');
            $post_request->update();
        }
        if ($result->wasRecentlyCreated) {
            $message = __('messages.save_form', ['form' => __('messages.booking')]);
        }

        if ($request->is('api/*')) {
            $response = [
                'message' => $message,
                'booking_id' => $result->id
            ];
            return comman_custom_response($response);
        }
        return redirect(route('booking.index'))->withSuccess($message);

    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $auth_user = authSession();

        $user = auth()->user();
        $user->last_notification_seen = now();
        $user->save();

        if (count($user->unreadNotifications) > 0) {

            foreach ($user->unreadNotifications as $notifications) {

                if ($notifications['data']['id'] == $id) {

                    $notification = $user->unreadNotifications->where('id', $notifications['id'])->first();
                    if ($notification) {
                        $notification->markAsRead();
                    }
                }

            }

        }


        $bookingdata = Booking::with('bookingExtraCharge', 'payment', 'service')->myBooking()->find($id);


        $tabpage = 'info';
        if (empty($bookingdata)) {
            $msg = __('messages.not_found_entry', ['name' => __('messages.booking')]);
            return redirect(route('booking.index'))->withError($msg);
        }
        if (count($auth_user->unreadNotifications) > 0) {
            $auth_user->unreadNotifications->where('data.id', $id)->markAsRead();
        }

        $pageTitle = __('messages.view_form_title', ['form' => __('messages.booking')]);
        return view('booking.view', compact('pageTitle', 'bookingdata', 'auth_user', 'tabpage'));
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        $auth_user = authSession();

        $bookingdata = Booking::myBooking()->find($id);

        $pageTitle = __('messages.update_form_title', ['form' => __('messages.booking')]);
        $relation = [
            'status' => BookingStatus::where('status', 1)->orderBy('sequence', 'ASC')->get()->pluck('label', 'value'),
        ];
        return view('booking.edit', compact('pageTitle', 'bookingdata', 'auth_user') + $relation);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(BookingUpdateRequest $request, $id)
    {
        if (demoUserPermission()) {
            return redirect()->back()->withErrors(trans('messages.demo_permission_denied'));
        }
        $data = $request->all();



        $data['date'] = isset($request->date) ? date('Y-m-d H:i:s', strtotime($request->date)) : date('Y-m-d H:i:s');
        $data['start_at'] = isset($request->start_at) ? date('Y-m-d H:i:s', strtotime($request->start_at)) : null;
        $data['end_at'] = isset($request->end_at) ? date('Y-m-d H:i:s', strtotime($request->end_at)) : null;


        $bookingdata = Booking::find($id);
        $paymentdata = Payment::where('booking_id', $id)->first();
        if ($data['status'] === 'hold') {
            if ($bookingdata->start_at == null && $bookingdata->end_at == null) {
                $duration_diff = duration($data['start_at'], $data['end_at'], 'in_minute');
                $data['duration_diff'] = $duration_diff;
            } else {
                if ($bookingdata->status == $data['status']) {
                    $booking_start_date = $bookingdata->start_at;
                    $request_start_date = $data['start_at'];
                    if ($request_start_date > $booking_start_date) {
                        $msg = __('messages.already_in_status', ['status' => $data['status']]);
                        return redirect()->back()->withSuccess($msg);
                    }
                } else {
                    $duration_diff = $bookingdata->duration_diff;
                    $new_diff = duration($bookingdata->start_at, $bookingdata->end_at, 'in_minute');
                    $data['duration_diff'] = $duration_diff + $new_diff;
                }
            }
        }
        if ($bookingdata->status != $data['status']) {
            $activity_type = 'update_booking_status';
        }
        if ($data['status'] == 'cancelled') {
            $activity_type = 'cancel_booking';
        }
        $data['reason'] = isset($data['reason']) ? $data['reason'] : null;
        $old_status = $bookingdata->status;

        $user = AUth::user();

        $data['user'] = $user;

        $bookingdata->update($data);
        if ($old_status != $data['status']) {
            $bookingdata->old_status = $old_status;

            $activity_data = [
                'activity_type' => $activity_type,
                'booking_id' => $id,
                'booking' => $bookingdata,
            ];
            $this->sendNotification($activity_data);

        }
        if ($bookingdata->payment_id != null) {
            $data['payment_status'] = isset($data['payment_status']) ? $data['payment_status'] : 'pending';
            $paymentdata->update($data);

            if ($bookingdata->payment_id != null) {
                $data['payment_status'] = isset($data['payment_status']) ? $data['payment_status'] : 'pending';
                $paymentdata->update($data);

                $activity_data = [
                    'activity_type' => 'payment_message_status',
                    'payment_status' => $data['payment_status'],
                    'booking_id' => $id,
                    'booking' => $bookingdata,
                ];
                $this->sendNotification($activity_data);

            }
        }
        $message = __('messages.update_form', ['form' => __('messages.booking')]);

        if ($request->is('api/*')) {

            return comman_message_response($message);
        }

        return redirect(route('booking.index'))->withSuccess($message);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        if (demoUserPermission()) {
            return redirect()->back()->withErrors(trans('messages.demo_permission_denied'));
        }
        $booking = Booking::find($id);

        $msg = __('messages.msg_fail_to_delete', ['item' => __('messages.booking')]);

        if ($booking != '') {
            Notification::whereJsonContains('data->id', $booking->id)->delete();
            $booking->delete();
            $msg = __('messages.msg_deleted', ['name' => __('messages.booking')]);
        }
        return comman_custom_response(['message' => $msg, 'status' => true]);
    }

    public function bookingAssignForm(Request $request)
    {

        $bookingdata = Booking::find($request->id);
        $pageTitle = __('messages.assign_form_title', ['form' => __('messages.booking')]);
        return view('booking.assigned_form', compact('bookingdata', 'pageTitle'));
    }

    public function bookingAssigned(Request $request)
    {
        $bookingdata = Booking::with('payment', 'handymanAdded')->find($request->id);

        $assigned_handyman_ids = [];
        $assigned_handyman = [];
        if ($bookingdata->handymanAdded()->count() > 0) {
            $assigned_handyman_ids = $bookingdata->handymanAdded()->pluck('handyman_id')->toArray();
            $bookingdata->handymanAdded()->delete();
            $assigned_handyman = $bookingdata->handymanAdded()->orderBy('id','desc')->withTrashed()->first();
            $message = __('messages.transfer_to_handyman');
            $activity_type = 'transfer_booking';
            $activity_data = [
                'activity_type' => $activity_type,
                'booking_id' => $bookingdata->id,
                'old_handyman_id' => $assigned_handyman ? $assigned_handyman : null,
                'booking' => $bookingdata,
            ];
            $this->sendNotification($activity_data);
        } 
        
        if ($request->handyman_id != null){
            $message = __('messages.assigned_to_handyman');
            $activity_type = 'assigned_booking';
        }
        $remove_notification_id = [];
        if ($request->handyman_id != null) {

            foreach ($request->handyman_id as $handyman) {

                $user = User::where('id', $handyman)->with('handymantype')->first();

                $assign_to_handyman = [
                    'booking_id' => $bookingdata->id,
                    'handyman_id' => $handyman,
                ];

                $remove_notification_id = removeArrayValue($assigned_handyman_ids, $handyman);
                $bookingdata->handymanAdded()->insert($assign_to_handyman);
            }
        }


        $bookingdata->status = 'accept';
        $bookingdata->save();
        $bookingdata = $bookingdata->with('handymanAdded', 'payment')->find($bookingdata->id);
        if ($bookingdata) {
            $this->addBookingCommission($bookingdata);
        }
        if($activity_type == "assigned_booking"){
            $activity_data = [
                'activity_type' => $activity_type,
                'booking_id' => $bookingdata->id,
                'booking' => $bookingdata,
            ];
            $this->sendNotification($activity_data);
        }

        $message = __('messages.save_form', ['form' => __('messages.booking')]);
        if ($request->is('api/*')) {
            return comman_message_response($message);
        }

        return response()->json(['status' => true, 'event' => 'callback', 'message' => $message]);
    }

    public function action(Request $request)
    {
        $id = $request->id;
        $type = $request->type;
        $booking_data = Booking::withTrashed()->where('id', $id)->first();
        $msg = __('messages.not_found_entry', ['name' => __('messages.booking')]);
        if ($request->type === 'restore') {
            if ($booking_data != '') {
                $booking_data->restore();
                $msg = __('messages.msg_restored', ['name' => __('messages.booking')]);
            }
        }
        if ($request->type === 'forcedelete') {
            $booking_data->forceDelete();
            $msg = __('messages.msg_forcedelete', ['name' => __('messages.booking')]);
        }

        return comman_custom_response(['message' => $msg, 'status' => true]);
    }
    public function bookingDetails(Request $request, $id)
    {
        $auth_user = authSession();
        if ($id != auth()->user()->id && !auth()->user()->hasRole(['admin', 'demo_admin'])) {
            return redirect(route('home'))->withErrors(trans('messages.demo_permission_denied'));
        }
        $providerdata = User::with([
            'providerBooking' => function ($query) {
                $query->orderBy('updated_at', 'desc');
            }
        ])->where('user_type', 'provider')->where('id', $id)->first();

        $earningData = array();
        foreach ($providerdata->providerBooking as $booking) {

            $booking_id = $booking->id;
            $provider_name = optional($booking->provider)->display_name ?? '-';
            $provider_image = getSingleMedia(optional($booking->provider), 'profile_image', null);
            $provider_contact = optional($booking->provider)->contact_number ?? '-';
            $provider_email = optional($booking->provider)->email ?? '-';
            $amount = $booking->total_amount;
            $payment_status = optional($booking->payment)->payment_status ?? null;
            $start_at = $booking->start_at;
            $end_at = $booking->end_at;
            $earningData[] = [
                'provider_id' => $providerdata->id,
                'booking_id' => $booking->id,
                'provider_name' => $provider_name,
                'provider_image' => $provider_image,
                'provider_email' => $provider_email,
                'provider_contact' => $provider_contact,
                'amount' => $amount,
                'payment_status' => $payment_status,
                'start_at' => $start_at,
                'end_at' => $end_at,
            ];


        }

        if ($request->ajax()) {
            return Datatables::of($earningData)
                ->addIndexColumn()
                ->addColumn('action', function ($row) {
                    $btn = '-';
                    $booking_id = $row['booking_id'];
                    $btn = "<a href=" . route('booking.show', $booking_id) . "><i class='fas fa-eye'></i></a>";
                    return $btn;
                })
                ->editColumn('provider_name', function ($row) {
                    return view('booking.provider', compact('row'));
                })
                ->editColumn('payment_status', function ($row) {
                    $payment_status = $row['payment_status'];

                    if ($payment_status !== null) {
                        $status = '<span class="text-center text-white badge bg-primary">' . str_replace('_', " ", ucfirst($payment_status)) . '</span>';
                    } else {
                        $status = '<span class="badge text-primary bg-primary-subtle">' . __('messages.pending') . '</span>';
                    }
                    return $status;
                })
                ->editColumn('start_at', function ($row) {
                    if (is_array($row)) {
                        $row = (object) $row;
                    }
                    $startAt = isset($row->start_at) ? $row->start_at : null;
                    if ($startAt !== null) {
                        $sitesetup = Setting::where('type', 'site-setup')->where('key', 'site-setup')->first();
                        $datetime = $sitesetup ? json_decode($sitesetup->value) : null;
                        $date = optional($datetime)->date_format && optional($datetime)->time_format
                            ? date(optional($datetime)->date_format, strtotime($startAt)) . '  ' . date(optional($datetime)->time_format, strtotime($startAt))
                            : $startAt;
                        return $date;
                    }
                    return null;
                })
                ->editColumn('end_at', function ($row) {
                    if (is_array($row)) {
                        $row = (object) $row;
                    }
                    $endAt = isset($row->end_at) ? $row->end_at : null;
                    if ($endAt !== null) {
                        $sitesetup = Setting::where('type', 'site-setup')->where('key', 'site-setup')->first();
                        $datetime = $sitesetup ? json_decode($sitesetup->value) : null;
                        $date = optional($datetime)->date_format && optional($datetime)->time_format
                            ? date(optional($datetime)->date_format, strtotime($endAt)) . '  ' . date(optional($datetime)->time_format, strtotime($endAt))
                            : $endAt;
                        return $date;
                    }
                    return null;
                })
                ->editColumn('amount', function ($row) {
                    return $row['amount'] ? getPriceFormat($row['amount']) : '-';
                })
                ->rawColumns(['action', 'payment_status', 'amount', 'check'])
                ->make(true);
        }
        if (empty($providerdata)) {
            $msg = __('messages.not_found_entry', ['name' => __('messages.provider')]);
            return redirect(route('provider.index'))->withError($msg);
        }
        $pageTitle = __('messages.bookings');
        return view('booking.details', compact('pageTitle', 'earningData', 'auth_user', 'providerdata'));
    }
    public function bookingstatus(Request $request, $id)
    {
        $tabpage = $request->tabpage;
        $auth_user = authSession();
        $user_id = $auth_user->id;
        $user_data = User::find($user_id);
        $bookingdata = Booking::with('handymanAdded', 'payment', 'bookingExtraCharge', 'bookingAddonService')->myBooking()->find($id);
        $payment = Payment::where('booking_id', $id)->orderBy('id', 'desc')->first() ?? null;
        $serviceconfig = Setting::getValueByKey('service-configurations', 'service-configurations');
        $advancePaymentPercentage = isset($serviceconfig->advance_paynment_percantage) ? $serviceconfig->advance_paynment_percantage : 0;
        $global_advance_payment = isset($serviceconfig->global_advance_payment) ? $serviceconfig->global_advance_payment : 0;
        $bookingdata->service->is_enable_advance_payment = $bookingdata->service->type == 'fixed' ? ($bookingdata->service->is_enable_advance_payment == 1 ? $bookingdata->service->is_enable_advance_payment : $global_advance_payment) : 0;
        $bookingdata->service->advance_payment_amount = $bookingdata->service->type == 'fixed' ? ($bookingdata->service->advance_payment_amount > 0 ? $bookingdata->service->advance_payment_amount : $advancePaymentPercentage) : 0;

        switch ($tabpage) {
            case 'info':
                $data = view('booking.' . $tabpage, compact('user_data', 'tabpage', 'auth_user', 'bookingdata', 'payment'))->render();
                break;
            case 'status':
                $data = view('booking.' . $tabpage, compact('user_data', 'tabpage', 'auth_user', 'bookingdata', 'payment'))->render();
                break;
            default:
                $data = view('booking.' . $tabpage, compact('tabpage', 'auth_user', 'bookingdata'))->render();
                break;
        }
        return response()->json($data);
    }
    public function createPDF($id)
    {
        $data = AppSetting::take(1)->first();
        $bookingdata = Booking::with('handymanAdded', 'payment', 'bookingExtraCharge', 'bookingPackage', 'bookingAddonService')->myBooking()->find($id);
        $payment = Payment::where('booking_id', $id)->orderBy('id', 'desc')->first() ?? null;
        $serviceconfig = Setting::getValueByKey('service-configurations', 'service-configurations');
        $advancePaymentPercentage = isset($serviceconfig->advance_paynment_percantage) ? $serviceconfig->advance_paynment_percantage : 0;
        $global_advance_payment = isset($serviceconfig->global_advance_payment) ? $serviceconfig->global_advance_payment : 0;
        $bookingdata->service->is_enable_advance_payment = $bookingdata->service->type == 'fixed' ? ($bookingdata->service->is_enable_advance_payment == 1 ? $bookingdata->service->is_enable_advance_payment : $global_advance_payment) : 0;
        $bookingdata->service->advance_payment_amount = $bookingdata->service->type == 'fixed' ? ($bookingdata->service->advance_payment_amount > 0 ? $bookingdata->service->advance_payment_amount : $advancePaymentPercentage) : 0;
        $pdf = Pdf::loadView('booking.invoice_pdf', ['bookingdata' => $bookingdata, 'data' => $data, 'payment' => $payment]);
        return $pdf->download('invoice_' . $bookingdata->id . '.pdf');
    }

    public function updateStatus(Request $request)
    {

        switch ($request->type) {
            case 'payment':
                $data = Payment::where('booking_id', $request->bookingId)->update(['payment_status' => $request->status]);
                break;
            default:

                $data = Booking::find($request->bookingId)->update(['status' => $request->status]);
                break;
        }

        return comman_custom_response(['message' => 'Status Updated', 'status' => true]);
    }

    public function saveBookingRating(Request $request)
    {
        $rating_data = $request->all();
        $result = BookingRating::updateOrCreate(['id' => $request->id], $rating_data);

        $message = __('messages.update_form', ['form' => __('messages.rating')]);
        if ($result->wasRecentlyCreated) {
            $message = __('messages.save_form', ['form' => __('messages.rating')]);
        }

        return redirect()->back()->withSuccess($message);
    }
    public function getPaymentMethod(Request $request)
    {
        $data = $request->all();
        $data['datetime'] = now();

        $data['payment_status'] = 'failed';

        $payment_data = Payment::where('booking_id', $data['booking_id'])->first();

        if (!empty($payment_data)) {
            $payment_data->update($data);
        } else {
            $payment_data = Payment::create($data);
        }
        $sitesetup = Setting::where('type', 'site-setup')->where('key', 'site-setup')->first();
        $sitesetupdata = $sitesetup ? json_decode($sitesetup->value, true) : null;

        $country_id = $sitesetupdata['default_currency'] ?? null;
        $country = Country::find($country_id);

        $data['currency_code'] = $country ? $country->currency_code : "USD";

        switch ($data['payment_type']) {
            case 'stripe':
                $data['payment_geteway_data'] = getPaymentMethodkey($data['payment_type']);
                break;

            default:

                break;
        }

        return comman_custom_response($data);
    }


    public function createStripePayment(Request $request)
    {

        $data = $request->all();

        $checkout_session = getstripepayments($data);

        if (isset($checkout_session['message'])) {

            return comman_custom_response($checkout_session);

        } else {
            Payment::where('booking_id', $data['booking_id'])->update(['other_transaction_detail' => $checkout_session['id']]);

            return comman_custom_response($checkout_session);
        }

    }

    public function saveStripePayment(Request $request, $id)
    {

        $type = $request->type;

        $result = Payment::where('booking_id', $id)->first();

        $stripe_session_id = $result->other_transaction_detail;
        $payment_type = $result->payment_type;

        $session_object = getstripePaymnetId($stripe_session_id, $payment_type);

        if ($session_object['payment_intent'] !== '' && $session_object['payment_status'] == 'paid') {

            $result->txn_id = $session_object['payment_intent'];

            if ($type == 'advance_payment') {

                $result->payment_status = 'advanced_paid';
            } else {

                $result->payment_status = 'paid';
            }

        }
        ;

        $result->update();

        $booking = Booking::find($id);
        if (!empty($result) && $result->payment_status == 'advanced_paid') {
            $booking->advance_paid_amount = $result->total_amount;
            $booking->status = 'pending';
        }
        $booking->payment_id = $result->id;
        $booking->update();

        $activity_data = [
            'activity_type' => 'payment_message_status',
            'payment_status' => str_replace("_", " ", ucfirst($result->payment_status)),
            'booking_id' => $booking->id,
            'booking' => $booking,
        ];
        $this->sendNotification($activity_data);

        return redirect('/booking-list');

    }

    public function getEarningsBreakdown(Request $request)
    {
        $authRole = auth()->user()->roles->pluck('name')->first();
        $bookings = Booking::query()->where('status','!=','cancelled')->with('commissionsdata', 'payment', 'handymanAdded');

        // Apply filters from the request
        if ($request->has('advanceFilter')) {
            $advanceFilter = $request->advanceFilter;

            // Regular filters
            $filters = [
                'customer_id' => 'customer_id',
                'service_id' => 'service_id',
                'provider_id' => 'provider_id',
                'handyman_id' => ['handymanAdded', 'handyman_id'],
                'booking_status' => 'status',
                'payment_status' => ['payment', 'payment_status'],
                'payment_type' => ['payment', 'payment_type'],
                'date_range' => null, // Special handling for date range
            ];

            foreach ($filters as $key => $filter) {
                if (!empty($advanceFilter[$key])) {
                    if ($key === 'date_range') {
                        $dates = explode(' to ', $advanceFilter['date_range']);
                        if (count($dates) === 2) {
                            $bookings->whereDate('date', '>=', $dates[0])
                                    ->whereDate('date', '<=', $dates[1]);
                        } elseif (count($dates) === 1) {
                            $bookings->whereDate('date', $dates[0]);
                        }
                    } else {
                        if (is_array($advanceFilter[$key])) {
                            if (is_array($filter)) {
                                $bookings->whereHas($filter[0], function ($query) use ($filter, $advanceFilter, $key) {
                                    $query->whereIn($filter[1], $advanceFilter[$key]);
                                });
                            } else {
                                $bookings->whereIn($filter, $advanceFilter[$key]);
                            }
                        } else {
                            $bookings->where($filter, $advanceFilter[$key]);
                        }
                    }
                }
            }
        }

        // Apply role-based filtering
        switch ($authRole) {
            case 'admin':
            case 'demo_admin':
                $bookings = $bookings->get();
                break;

            case 'provider':
                $bookings = $bookings->where('provider_id', auth()->user()->id)->get();
                break;

            case 'handyman':
                $bookings = $bookings->whereHas('handymanAdded', function ($query) {
                    $query->where('handyman_id', auth()->user()->id);
                })->get();
                break;

            default:
                $bookings = collect();
                break;
        }

        // Initialize earnings array
        $earnings = [
            'admin' => 0,
            'provider' => 0,
            'handyman' => 0,
            'tax' => 0,
            'discount' => 0,
            'total' => 0,
            'totalAmountWithDiscount' => 0,
            'totalAmountWithoutDiscount' => 0,
        ];

        foreach ($bookings as $booking) {
            // Get the raw total amount before any adjustments
            $rawTotal = $booking->total_amount + ($booking->final_discount_amount ?? 0);

            // // Calculate actual total after discount
            $actualTotal = $booking->total_amount;

            // Handle commission distribution
            if ($booking->handymanAdded->count() > 0) {
                foreach ($booking->commissionsdata as $commission) {
                    switch ($commission->user_type) {
                        case 'admin':
                            $earnings['admin'] += $commission->commission_amount;
                            break;
                        case 'provider':
                            $earnings['provider'] += $commission->commission_amount;
                            break;
                        case 'handyman':
                            $earnings['handyman'] += $commission->commission_amount;
                            break;
                    }
                }
                 // Track components
            $earnings['tax'] += $booking->final_total_tax ?? 0;
            $earnings['discount'] += $booking->final_discount_amount ?? 0;

            // Update totals - switched rawTotal and actualTotal
            $earnings['totalAmountWithDiscount'] += $rawTotal;
            $earnings['totalAmountWithoutDiscount'] += $actualTotal;
            $earnings['total'] += $rawTotal - ($booking->final_discount_amount ?? 0); // Changed to rawTotal to show amount before discount

            }
            // else {
            //     // If no handyman, provider gets the full amount after discount and tax
            //     $earnings['provider'] += ($actualTotal - ($booking->final_total_tax ?? 0));
            // }


        }

        // Round all values to 2 decimal places for consistency
        foreach ($earnings as $key => $value) {
            $earnings[$key] = round($value, 2);
        }
        // dd($earnings['total']);

        return response()->json([
            'totalEarning' => number_format($earnings['total'], 2),
            'earnings' => $earnings,
            'userRole' => $authRole,
        ]);
    }



}


