<?php

namespace Modules\Transport\Controllers;

use App\Controllers\BaseController;
use App\Models\TransportAiPlanModel;
use App\Models\TransportAiPlanRouteModel;
use App\Models\TransportAiPlanStopModel;
use App\Models\TransportContractSiteModel;
use App\Models\TransportDriverModel;
use App\Models\TransportVehicleModel;
use Modules\Transport\Services\Ai\AiPlanScopeService;
use Modules\Transport\Services\Ai\TransportAiPlanService;
use Modules\Transport\Services\MapSettingsService;

class AiPlannerController extends BaseController
{
    protected TransportAiPlanModel $plans;
    protected TransportAiPlanService $service;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
        $this->plans   = new TransportAiPlanModel();
        $this->service = new TransportAiPlanService();
    }

    public function index()
    {
        $search = trim((string) $this->request->getGet('q'));
        $status = $this->request->getGet('status') ?: null;

        $entries = $this->plans
            ->scopeForList($search ?: null, $status)
            ->orderBy('transport_ai_plans.id', 'DESC')
            ->paginate(25);

        return view('Modules\Transport\Views\ai\plans\index', array_merge($this->baseViewData(), [
            'title'        => 'AI Transport Plans',
            'entries'      => $entries,
            'pager'        => $this->plans->pager,
            'filters'      => compact('search', 'status'),
            'statusCounts' => $this->plans->countByStatus(),
        ]));
    }

    public function generateForm()
    {
        $contractSearch = trim((string) $this->request->getGet('contract_q'));
        $region         = (new AiPlanScopeService())->normalizeRegion($this->request->getGet('region'));
        $batchLimit     = (new AiPlanScopeService())->normalizeBatchLimit($this->request->getGet('batch_limit'));

        $siteModel = new TransportContractSiteModel();
        $regions   = $siteModel->getPlannableRegions();
        $sites     = $siteModel->getActivePlannableOptions(
            $contractSearch !== '' ? $contractSearch : null,
            $region,
            500
        );
        $siteTotal = $region !== null
            ? $siteModel->countActivePlannable($region)
            : $siteModel->countActivePlannable();

        $scopeService = new AiPlanScopeService();
        $oldSelected  = old('contract_ids');
        $autoSelected = $scopeService->defaultSelection($region, $batchLimit, $sites);
        $selectedIds  = is_array($oldSelected) && $oldSelected !== []
            ? array_map('intval', $oldSelected)
            : $autoSelected;

        $assignedStaff  = $siteModel->countAssignedActiveStaff();
        $sitesWithShift = $siteModel->countActivePlannableWithShift();

        $readiness = [
            'contract_sites'   => $siteTotal,
            'assigned_staff'   => $assignedStaff,
            'sites_with_shift' => $sitesWithShift,
            'vehicles'         => (new TransportVehicleModel())->where('status', 'active')->where('capacity >', 0)->countAllResults(),
            'drivers'          => (new TransportDriverModel())->where('status', 'active')->countAllResults(),
        ];

        return view('Modules\Transport\Views\ai\plans\generate', array_merge($this->baseViewData(), [
            'title'          => 'Generate AI Transport Plan',
            'sites'          => $sites,
            'siteTotal'      => $siteTotal,
            'contractSearch' => $contractSearch,
            'regions'        => $regions,
            'region'         => $region,
            'batchLimit'     => $batchLimit,
            'selectedIds'    => $selectedIds,
            'batchLimits'    => TransportContractSiteModel::BATCH_LIMITS,
            'readiness'      => $readiness,
        ]));
    }

    public function store()
    {
        if (! $this->validate([
            'plan_start_date' => 'required|valid_date[Y-m-d]',
            'plan_end_date'   => 'required|valid_date[Y-m-d]',
            'title'           => 'permit_empty|max_length[200]',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $scopeService = new AiPlanScopeService();
        $scope        = $scopeService->resolve(
            is_array($this->request->getPost('contract_ids')) ? $this->request->getPost('contract_ids') : null,
            $this->request->getPost('region'),
            (int) ($this->request->getPost('batch_limit') ?? AiPlanScopeService::DEFAULT_BATCH_LIMIT)
        );

        if ($scope['error'] !== null) {
            return redirect()->back()->withInput()->with('errors', ['generate' => $scope['error']]);
        }

        $result = $this->service->generate(
            (string) $this->request->getPost('plan_start_date'),
            (string) $this->request->getPost('plan_end_date'),
            $scope['contract_ids'],
            (int) $this->session->get('user_id'),
            $this->request->getPost('title'),
            $scope['batch_limit']
        );

        if (! $result['success']) {
            return redirect()->back()->withInput()->with('errors', $result['errors']);
        }

        return redirect()->to('/transport/ai/plans/' . $result['id'])
            ->with('success', 'AI transportation plan generated. Review it and submit for approval.');
    }

    public function show(int $id)
    {
        $plan = $this->plans->scopeForList()->where('transport_ai_plans.id', $id)->first();
        if (! $plan) {
            return redirect()->to('/transport/ai/plans')->with('error', 'Plan not found.');
        }

        $routes = (new TransportAiPlanRouteModel())->getForPlan($id);
        $stops  = (new TransportAiPlanStopModel())->getForPlanGrouped($id);

        return view('Modules\Transport\Views\ai\plans\show', array_merge($this->baseViewData(), [
            'title'        => $plan['number'],
            'plan'         => $plan,
            'routes'       => $routes,
            'stops'        => $stops,
            'conflicts'    => json_decode((string) $plan['conflicts_json'], true) ?: [],
            'fleetSummary' => json_decode((string) $plan['fleet_summary_json'], true) ?: [],
            'mapSettings'  => (new MapSettingsService())->getSettings(),
            'canApprove'   => $this->userCan('transport_ai.approve'),
            'canGenerate'  => $this->userCan('transport_ai.generate'),
        ]));
    }

    public function submit(int $id)
    {
        $result = $this->service->submitForApproval($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->to('/transport/ai/plans/' . $id)->with('error', $result['error']);
        }

        return redirect()->to('/transport/ai/plans/' . $id)->with('success', 'Plan submitted for manager approval.');
    }

    public function approve(int $id)
    {
        $result = $this->service->approve($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->to('/transport/ai/plans/' . $id)->with('error', $result['error']);
        }

        return redirect()->to('/transport/ai/plans/' . $id)
            ->with('success', sprintf('Plan approved. %d official transport schedules were published.', $result['published']));
    }

    public function reject(int $id)
    {
        $result = $this->service->reject($id, (string) $this->request->getPost('rejection_reason'), (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->to('/transport/ai/plans/' . $id)->with('error', $result['error']);
        }

        return redirect()->to('/transport/ai/plans/' . $id)->with('success', 'Plan rejected.');
    }

    public function destroy(int $id)
    {
        $result = $this->service->delete($id, (int) $this->session->get('user_id'));
        if (! $result['success']) {
            return redirect()->to('/transport/ai/plans')->with('error', $result['error']);
        }

        return redirect()->to('/transport/ai/plans')->with('success', 'Plan deleted.');
    }

    protected function userCan(string $slug): bool
    {
        if ($this->isAdministrator()) {
            return true;
        }

        $roleId = (int) $this->session->get('role_id');

        return $roleId > 0 && (new \App\Models\RolePermissionModel())->roleHasPermission($roleId, $slug);
    }
}
