<?php

namespace App\Http\Controllers\CounterManager;

use Carbon\Carbon;
use App\Models\Trip;
use App\Models\Driver;
use App\Models\Vehicle;
use App\Models\Stoppage;
use App\Constants\Status;
use App\Models\FleetType;
use App\Models\TripRoute;
use App\Models\Supervisor;
use App\Models\BookedTicket;
use App\Models\CounterManager;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CounterManagerController extends Controller {
    public function dashboard(Request $request) {
        $pageTitle = 'Dashboard';
        $counter = authUser('counterManager')->counter;

        $stoppages = Stoppage::active()->get();

        if ($request->has('from') || $request->has('to') || $request->has('date_of_journey')) {
            $tripQuery = Trip::availableTrip()
                ->selectRaw('trips.*, ticket_prices.id as ticket_price_id')
                ->rightJoin('ticket_prices', function ($join) {
                    $join->on('trips.vehicle_route_id', '=', 'ticket_prices.vehicle_route_id')
                        ->on('trips.fleet_type_id', '=', 'ticket_prices.fleet_type_id');
                });

            if ($request->filled('to')) {
                $from = $request->from;
                $to   = $request->to;

                $tripQuery->whereHas('route', function ($query) use ($from, $to) {
                    $query->whereRaw("JSON_CONTAINS(stoppages, JSON_QUOTE(?))", [$from])
                        ->whereRaw("JSON_CONTAINS(stoppages, JSON_QUOTE(?))", [$to])
                        ->whereRaw("JSON_SEARCH(stoppages, 'one', ?) < JSON_SEARCH(stoppages, 'one', ?)", [$from, $to]);
                });
            } else {
                $tripQuery->whereHas('route', function ($query) {
                    $query->mangerRoute();
                })->where('end_to', '!=', $counter?->id);
            }

            $trips = $tripQuery->whereDate('start_time', showDateTime($request->date_of_journey, 'Y-m-d'))->paginate(getPaginate());
        } else {
            $trips = Trip::whereIn('status', [Status::TRIP_INITIATED, Status::TRIP_RUNNING])
                ->selectRaw('trips.*, ticket_prices.id as ticket_price_id')
                ->rightJoin('ticket_prices', function ($join) {
                    $join->on('trips.vehicle_route_id', '=', 'ticket_prices.vehicle_route_id')
                        ->on('trips.fleet_type_id', '=', 'ticket_prices.fleet_type_id');
                })->whereHas('route', function ($query) {
                    $query->mangerRoute();
                })->where('end_to', '!=', $counter->id)->where('start_time', '>=', now()->format('Y-m-d H:i:s'))->orderBy('id', 'DESC')->paginate(getPaginate());
        }


        $source_destination = [];
        if ($request->filled('to')) {
            $source_destination = [$request->from, $request->to];
        }

        return view('counter_manager.dashboard', compact('pageTitle', 'counter', 'stoppages', 'trips', 'source_destination'));
    }

    public function trips() {
        $pageTitle = 'Trips';
        $manager   = authUser('counterManager');
        $counter   = $manager->counter()->first();
        $tripQuery = Trip::with(['fleetType', 'route', 'vehicle', 'driver', 'supervisor'])
            ->selectRaw('trips.*, ticket_prices.id as ticket_price_id')
            ->rightJoin('ticket_prices', function ($join) {
                $join->on('trips.vehicle_route_id', '=', 'ticket_prices.vehicle_route_id')
                    ->on('trips.fleet_type_id', '=', 'ticket_prices.fleet_type_id');
            })
            ->searchable(['title', 'vehicle:vehicle_no']);

        if (request()->filled('departure_date') && request()->filled('departure_time')) {
            $tripQuery->dateFilterByColumn('start_time', 'departure_date')
                ->whereTime('start_time', request('departure_time'));
        } else if (request()->filled('departure_date')) {
            $tripQuery->dateFilterByColumn('start_time', 'departure_date');
        } else if (request()->filled('departure_time')) {
            $tripQuery->whereTime('start_time', request('departure_time'));
        } else if (!request()->filled('arrival_date') && !request()->filled('arrival_time')) {
            $tripQuery->whereDate('start_time', today());
        }

        if (request()->filled('arrival_date') && request()->filled('arrival_time')) {
            $tripQuery->whereDate('expected_end_time', request('arrival_date'))
                ->whereTime('expected_end_time', request('arrival_time'));
        } elseif (request()->filled('arrival_date')) {
            $tripQuery->whereDate('expected_end_time', request('arrival_date'));
        } elseif (request()->filled('arrival_time')) {
            $tripQuery->whereTime('expected_end_time', request('arrival_time'));
        }

        if (request()->filled('status')) {
            $tripQuery->where('status', request('status'));
        }

        if (request()->filled('driver_id')) {
            $tripQuery->where('driver_id', request('driver_id'));
        }

        if (request()->filled('supervisor_id')) {
            $tripQuery->where('supervisor_id', request('supervisor_id'));
        }

        if (request()->filled('vehicle_id')) {
            $tripQuery->where('vehicle_id', request('vehicle_id'));
        }

        if (empty(request()->all())) {
            $tripQuery->whereHas('route', function ($query) {
                $query->mangerRoute();
            })->where('end_to', '!=', $counter->id);
        }

        $trips = $tripQuery->orderBy('start_time', 'asc')->paginate(getPaginate());

        $drivers     = Driver::active()->orderByDesc('id')->get();
        $supervisors = Supervisor::active()->orderByDesc('id')->get();
        $vehicles    = Vehicle::active()->get();
        $routes      = TripRoute::active()->get();
        $fleetTypes  = FleetType::active()->get();
        return view('counter_manager.trips.index', compact('pageTitle', 'trips', 'drivers', 'supervisors', 'vehicles', 'routes', 'fleetTypes', 'counter'));
    }

    public function ticketPrint($id) {
        $bookedTicket    = BookedTicket::with('trip', 'trip.route')->findOrFail($id);
        $pageTitle = 'Print Ticket';
        return view('partials.ticket_invoice', compact('bookedTicket', 'pageTitle'));
    }

    public function statistics() {
        $pageTitle         = 'Sales Statistics';
        $monthlySalesQuery = BookedTicket::counterTicket();
        $yearlySalesQuery  = BookedTicket::counterTicket();
        $dailySaleQuery    = BookedTicket::counterTicket();
        $allSaleQuery      = BookedTicket::counterTicket();
        if (request()->counter_manager_id) {
            $monthlySalesQuery->where('counter_manager_id', request()->counter_manager_id);
            $yearlySalesQuery->where('counter_manager_id', request()->counter_manager_id);
            $dailySaleQuery->where('counter_manager_id', request()->counter_manager_id);
            $allSaleQuery->where('counter_manager_id', request()->counter_manager_id);
        }

        $monthlySales = $monthlySalesQuery->whereMonth('created_at', date('m'))
            ->get()
            ->groupBy(function ($date) {
                return Carbon::parse($date->created_at)->format('F d');
            });

        $yearlySales = $yearlySalesQuery->whereYear('created_at', date('Y'))
            ->get()
            ->groupBy(function ($date) {
                return Carbon::parse($date->created_at)->format('F');
            });

        $dailySale = $dailySaleQuery->whereDate('created_at', date('Y-m-d'))
            ->selectRaw('sum(sub_total) AS total_sales , sum(ticket_count) as total_ticket')
            ->first();

        $allSale = $allSaleQuery->selectRaw('sum(sub_total) AS total_sales , sum(ticket_count) as total_ticket')
            ->first();

        $monthlySale = [];
        $yearlySale  = [];

        $monthlyTicketCount = 0;
        foreach ($monthlySales as $key => $value) {
            $sPrice = 0;
            foreach ($value as $item) {
                $sPrice += $item->sub_total;
                $monthlyTicketCount += $item->ticket_count;
            }
            $monthlySale[$key] = $sPrice;
        }

        $yearlyTicketCount = 0;
        foreach ($yearlySales as $key => $value) {
            $sPrice = 0;
            foreach ($value as $item) {
                $sPrice += $item->sub_total;
                $yearlyTicketCount += $item->ticket_count;
            }
            $yearlySale[$key] = $sPrice;
        }
        if (request()->ajax()) {
            $html              = view('counter_manager.partials.statistics', compact('monthlySale', 'monthlyTicketCount', 'dailySale', 'yearlySale', 'yearlyTicketCount', 'allSale'))->render();
            $yearlySaleKeys    = array_keys($yearlySale);
            $yearlySaleValues  = array_values($yearlySale);
            $monthlySaleKeys   = array_keys($monthlySale);
            $monthlySaleValues = array_values($monthlySale);
            return response()->json([
                'monthlySale'     => $monthlySaleValues,
                'monthlySaleKeys' => $monthlySaleKeys,
                'yearlySale'      => $yearlySaleValues,
                'yearlySaleKeys'  => $yearlySaleKeys,
                'html'            => $html,
            ]);
        }
        $counterManagers = $this->counterManagers();
        return view('counter_manager.sales_statistics', compact('pageTitle', 'monthlySale', 'monthlyTicketCount', 'dailySale', 'yearlySale', 'yearlyTicketCount', 'allSale', 'counterManagers'));
    }

    public function todaysBookings() {
        $pageTitle = 'Today\'s Bookings';
        request()->merge(['date' => Carbon::now()->format('F d, Y')]);
        $data            = $this->getTicketData();
        $soldTickets     = $data['tickets'];
        $trips           = $data['trips'];
        $routes          = $data['routes'];
        $stoppages       = $data['stoppages'];
        $counterManagers = $this->counterManagers();
        return view('counter_manager.booking.list', compact('pageTitle', 'soldTickets', 'routes', 'trips', 'counterManagers', 'stoppages'));
    }

    public function cancelBooking($id) {
        $bookedTicket = BookedTicket::whereId($id)->with('trip')->firstOrFail();
        $tripTime     = Carbon::parse($bookedTicket->trip->start_time);
        if (Carbon::parse(now()) > $tripTime->subHours(gs('ticket_cancel_time') ?? 0) || $bookedTicket->trip->status == Status::TRIP_COMPLETED) {
            $notify[] = ['error', 'Sorry cancellation time is over'];
            return back()->withNotify($notify);
        }
        $bookedTicket->cancel_by = authUser('counterManager')->id;
        $bookedTicket->status    = Status::BOOKED_CANCELED;
        $bookedTicket->cancel_fee = (gs('ticket_cancel_fee') * $bookedTicket->ticket_count);
        $bookedTicket->cancel_time = now();
        $bookedTicket->save();
        $message = 'Booking Canceled Successfully';

        $notify[] = ['success', $message];
        return back()->withNotify($notify);
    }

    public function allBookings() {
        $pageTitle       = 'All Bookings';
        $data            = $this->getTicketData();
        $soldTickets     = $data['tickets'];
        $trips           = $data['trips'];
        $routes          = $data['routes'];
        $stoppages       = $data['stoppages'];
        $counterManagers = $this->counterManagers();
        return view('counter_manager.booking.list', compact('soldTickets', 'pageTitle', 'routes', 'trips', 'counterManagers', 'stoppages'));
    }

    public function cancelledBookings() {
        $pageTitle       = 'Canceled Bookings';
        $data            = $this->getTicketData('canceled');
        $soldTickets     = $data['tickets'];
        $trips           = $data['trips'];
        $routes          = $data['routes'];
        $stoppages       = $data['stoppages'];
        $counterManagers = $this->counterManagers();
        return view('counter_manager.booking.list', compact('pageTitle', 'soldTickets', 'routes', 'trips', 'counterManagers', 'stoppages'));
    }

    private function getTicketData($scope = null) {
        $ticketQuery = BookedTicket::searchable(['pnr_number'])
            ->counter()
            ->filter(['counter_manager_id', 'cancel_by', 'trip:vehicle_route_id', 'trip_id', 'boarding_point'])
            ->dateFilter()
            ->dateFilterByColumn('date_of_journey', 'date_of_journey')
            ->dateFilterByColumn('cancel_time', 'cancel_time')
            ->with('trip', 'trip.route', 'counterManager', 'user', 'guestUser', 'boarding', 'pickup', 'drop')
            ->orderByDesc('id');
        if ($scope) {
            $ticketQuery->$scope();
        }
        $data['tickets'] = $ticketQuery->paginate(getPaginate());
        $data['trips']   = Trip::whereHas('route', function ($query) {
            $query->mangerRoute();
        })
            ->select('id', 'title')
            ->get();
        $data['routes'] = TripRoute::active()
            ->whereJsonContains('stoppages', (string) authUser('counterManager')->stoppage_id)
            ->get();
        $data['stoppages'] = Stoppage::active()->orderBy('name')->get();
        return $data;
    }

    private function counterManagers() {
        return CounterManager::where('stoppage_id', authUser('counterManager')->stoppage_id)->get();
    }

    public function banned() {
        $manager = authUser('counterManager');
        if ($manager->status) {
            return to_route('counter.manager.dashboard');
        }
        Auth::guard('counterManager')->logout();
        return to_route('counter.manager.login');
    }
}
