<?php

namespace Modules\Transport\Controllers;

use App\Controllers\BaseController;
use App\Models\ActivityLogModel;
use App\Models\AttendanceShiftModel;
use App\Models\ContractModel;
use App\Models\TransportContractSiteModel;
use App\Models\TransportLocationModel;

class ContractSiteController extends BaseController
{
    protected TransportContractSiteModel $sites;

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

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

        $entries = $this->sites
            ->scopeForList($search ?: null, $status)
            ->orderBy('contracts.title', 'ASC')
            ->paginate(25);

        return view('Modules\Transport\Views\ai\contract_sites\index', array_merge($this->baseViewData(), [
            'title'   => 'Contract Transport Sites',
            'entries' => $entries,
            'pager'   => $this->sites->pager,
            'filters' => compact('search', 'status'),
        ]));
    }

    public function createForm()
    {
        $contractSearch  = trim((string) $this->request->getGet('contract_q'));
        $locationSearch  = trim((string) $this->request->getGet('location_q'));

        return view('Modules\Transport\Views\ai\contract_sites\create', array_merge($this->baseViewData(), [
            'title'     => 'Map Contract to Site',
            'site'      => [],
            'contracts' => $this->contractsWithoutSite($contractSearch),
            'locations' => (new TransportLocationModel())->getWithCoordinates($locationSearch !== '' ? $locationSearch : null, 150),
            'shifts'    => (new AttendanceShiftModel())->where('status', 'active')->orderBy('start_time', 'ASC')->findAll(),
        ]));
    }

    public function store()
    {
        if (! $this->validate([
            'contract_id'           => 'required|integer',
            'transport_location_id' => 'required|integer',
            'default_shift_id'      => 'permit_empty|integer',
            'status'                => 'permit_empty|in_list[active,inactive]',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $contractId = (int) $this->request->getPost('contract_id');
        if ($this->sites->getForContract($contractId)) {
            return redirect()->back()->withInput()->with('errors', ['contract_id' => 'This contract is already mapped to a site. Edit the existing mapping instead.']);
        }

        $userId = (int) $this->session->get('user_id');
        $this->sites->insert($this->mapInput($userId) + ['contract_id' => $contractId, 'created_by' => $userId], true);
        $id = (int) $this->sites->getInsertID();
        (new ActivityLogModel())->log('transport_ai', 'contract_site_created', $userId, "Mapped contract #{$contractId} to transport site (mapping #{$id})", (string) $id);

        return redirect()->to('/transport/ai/contract-sites')->with('success', 'Contract site mapping saved.');
    }

    public function editForm(int $id)
    {
        $site = $this->sites->scopeForList()->where('transport_contract_sites.id', $id)->first();
        if (! $site) {
            return redirect()->to('/transport/ai/contract-sites')->with('error', 'Mapping not found.');
        }

        return view('Modules\Transport\Views\ai\contract_sites\edit', array_merge($this->baseViewData(), [
            'title'     => 'Edit Contract Site',
            'site'      => $site,
            'locations' => (new TransportLocationModel())->getWithCoordinates(trim((string) $this->request->getGet('location_q')) ?: null, 150),
            'shifts'    => (new AttendanceShiftModel())->where('status', 'active')->orderBy('start_time', 'ASC')->findAll(),
        ]));
    }

    public function update(int $id)
    {
        if (! $this->sites->find($id)) {
            return redirect()->to('/transport/ai/contract-sites')->with('error', 'Mapping not found.');
        }

        if (! $this->validate([
            'transport_location_id' => 'required|integer',
            'default_shift_id'      => 'permit_empty|integer',
            'status'                => 'permit_empty|in_list[active,inactive]',
        ])) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $userId = (int) $this->session->get('user_id');
        $this->sites->update($id, $this->mapInput($userId));
        (new ActivityLogModel())->log('transport_ai', 'contract_site_updated', $userId, "Updated contract site mapping #{$id}", (string) $id);

        return redirect()->to('/transport/ai/contract-sites')->with('success', 'Contract site mapping updated.');
    }

    public function destroy(int $id)
    {
        if (! $this->sites->find($id)) {
            return redirect()->to('/transport/ai/contract-sites')->with('error', 'Mapping not found.');
        }

        $userId = (int) $this->session->get('user_id');
        $this->sites->delete($id);
        (new ActivityLogModel())->log('transport_ai', 'contract_site_deleted', $userId, "Deleted contract site mapping #{$id}", (string) $id);

        return redirect()->to('/transport/ai/contract-sites')->with('success', 'Contract site mapping deleted.');
    }

    protected function mapInput(int $userId): array
    {
        $status  = (string) $this->request->getPost('status');
        $shiftId = $this->request->getPost('default_shift_id');

        return [
            'transport_location_id' => (int) $this->request->getPost('transport_location_id'),
            'default_shift_id'      => $shiftId ? (int) $shiftId : null,
            'status'                => in_array($status, TransportContractSiteModel::STATUSES, true) ? $status : 'active',
            'notes'                 => trim((string) $this->request->getPost('notes')) ?: null,
            'updated_by'            => $userId,
        ];
    }

    protected function contractsWithoutSite(?string $search = null): array
    {
        $builder = (new ContractModel())
            ->select('contracts.id, contracts.number, contracts.title')
            ->join('transport_contract_sites tcs', 'tcs.contract_id = contracts.id', 'left')
            ->where('contracts.status', 'active')
            ->where('tcs.id IS NULL');

        if ($search) {
            $builder->groupStart()
                ->like('contracts.number', $search)
                ->orLike('contracts.title', $search)
                ->groupEnd();
        }

        return $builder->orderBy('contracts.title', 'ASC')->limit(100)->findAll();
    }
}
