<?php

class LoadController extends Controller
{
    private Load $loads; private Broker $brokers; private Carrier $carriers; private Driver $drivers; private Truck $trucks; private Trailer $trailers; private Document $documents; private TemperatureLog $temperatures;

    public function __construct()
    {
        $this->loads=new Load();$this->brokers=new Broker();$this->carriers=new Carrier();$this->drivers=new Driver();$this->trucks=new Truck();$this->trailers=new Trailer();$this->documents=new Document();$this->temperatures=new TemperatureLog();
    }

    public function index(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);$search=trim((string)($_GET['search']??''));$loads=$this->loads->all($search?:null);$this->view('loads/index',compact('loads','search'));clear_old();
    }

    public function board(): void { Auth::requireRole(['owner','admin','dispatcher','team']);$board=$this->loads->board();$this->view('loads/board',compact('board')); }

    public function calendar(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);$month=preg_match('/^\d{4}-\d{2}$/',(string)($_GET['month']??''))?$_GET['month']:date('Y-m');$start=$month.'-01';$end=date('Y-m-t',strtotime($start));
        $stmt=Database::connection()->prepare("SELECT loads.id,loads.load_number,loads.status,loads.pickup_location,loads.delivery_location,loads.pickup_datetime,loads.delivery_datetime,loads.temperature_controlled,loads.temperature_setpoint,loads.temperature_unit,drivers.name driver_name,trucks.unit_number,carriers.company_name carrier_name FROM loads LEFT JOIN drivers ON drivers.id=loads.driver_id LEFT JOIN trucks ON trucks.id=loads.truck_id LEFT JOIN carriers ON carriers.id=loads.carrier_id WHERE DATE(loads.pickup_datetime) BETWEEN ? AND ? OR DATE(loads.delivery_datetime) BETWEEN ? AND ? ORDER BY COALESCE(loads.pickup_datetime,loads.delivery_datetime)");
        $stmt->execute([$start,$end,$start,$end]);$loads=$stmt->fetchAll();$events=[];foreach($loads as $load){if($load['pickup_datetime'])$events[date('Y-m-d',strtotime($load['pickup_datetime']))][]=['type'=>'pickup','load'=>$load];if($load['delivery_datetime'])$events[date('Y-m-d',strtotime($load['delivery_datetime']))][]=['type'=>'delivery','load'=>$load];}
        $this->view('loads/calendar',compact('month','start','end','events'));
    }

    public function create(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);$load=null;$documents=[];$events=[];$locations=[];$temperatureLogs=[];
        $brokers=$this->brokers->active();$carriers=$this->carriers->active();$drivers=$this->drivers->available();$trucks=$this->trucks->available();$trailers=$this->trailers->available();$statuses=Load::STATUSES;
        $preselectedCarrier=(int)($_GET['carrier_id']??0);$this->view('loads/create',compact('load','documents','events','locations','temperatureLogs','brokers','carriers','drivers','trucks','trailers','statuses','preselectedCarrier'));
    }

    public function store(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);Csrf::verify();
        if(trim((string)($_POST['load_number']??''))===''||trim((string)($_POST['pickup_location']??''))===''||trim((string)($_POST['delivery_location']??''))===''){set_old($_POST);$this->flash('danger','Load number, pickup, and delivery locations are required.');$this->redirect('/loads/create');}
        $id=$this->loads->create($_POST);log_activity('load_created','Created load '.trim((string)$_POST['load_number']));$this->flash('success','Load created successfully.');$this->redirect('/loads/edit?id='.$id);
    }

    public function edit(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);$load=$this->loads->find((int)($_GET['id']??0));if(!$load){$this->flash('danger','Load not found.');$this->redirect('/loads');}
        $documents=$this->documents->forLoadWithStops((int)$load['id']);$brokers=$this->brokers->active();$carriers=$this->carriers->active();$drivers=$this->drivers->available();$trucks=$this->trucks->available();$trailers=$this->trailers->available();$statuses=Load::STATUSES;$events=$this->loads->events((int)$load['id']);$locations=$this->loads->latestLocations((int)$load['id']);$temperatureLogs=$this->temperatures->forLoad((int)$load['id']);$preselectedCarrier=0;
        $this->view('loads/edit',compact('load','documents','brokers','carriers','drivers','trucks','trailers','statuses','events','locations','temperatureLogs','preselectedCarrier'));
    }

    public function update(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);Csrf::verify();$id=(int)($_POST['id']??0);
        if(!$id||trim((string)($_POST['load_number']??''))===''||trim((string)($_POST['pickup_location']??''))===''||trim((string)($_POST['delivery_location']??''))===''){set_old($_POST);$this->flash('danger','Load number, pickup, and delivery locations are required.');$this->redirect('/loads/edit?id='.$id);}
        $this->loads->update($id,$_POST);log_activity('load_updated','Updated load '.trim((string)$_POST['load_number']));$this->flash('success','Load updated successfully.');$this->redirect('/loads/edit?id='.$id);
    }

    public function updateStatus(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);Csrf::verify();$id=(int)($_POST['id']??0);$status=$_POST['status']??'new';$this->loads->updateStatus($id,$status);log_activity('load_status_updated','Updated load status to '.readable_status($status));$this->flash('success','Load status updated.');$this->back();
    }

    public function storeTemperature(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);Csrf::verify();$load=$this->loads->find((int)($_POST['load_id']??0));
        if(!$load||($_POST['temperature']??'')===''||!is_numeric($_POST['temperature'])){$this->flash('danger','A valid temperature reading is required.');$this->back();}
        $data=$_POST;$data['trailer_id']=$load['trailer_id']??null;$data['driver_id']=$load['driver_id']??null;$this->temperatures->create($data);
        $temperature=(float)$_POST['temperature'];$outsideRange=($load['temperature_min']!==null&&$temperature<(float)$load['temperature_min'])||($load['temperature_max']!==null&&$temperature>(float)$load['temperature_max']);
        $this->loads->addEvent((int)$load['id'],'temperature_recorded','Temperature recorded: '.$temperature.($_POST['temperature_unit']??$load['temperature_unit']));
        if($outsideRange){notify_roles(['owner','admin','dispatcher'],'Temperature alert',$load['load_number'].' is outside the required temperature range.','/loads/edit?id='.(int)$load['id'],'danger');notify_carrier_users((int)($load['carrier_id']??0),'Temperature alert',$load['load_number'].' is outside the required temperature range.','/carrier/loads/show?id='.(int)$load['id'],'danger');}
        log_activity('temperature_recorded','Recorded temperature for load '.$load['load_number']);$this->flash('success','Temperature reading saved.');$this->redirect('/loads/edit?id='.$load['id']);
    }

    public function delete(): void
    {
        Auth::requireRole(['owner','admin','dispatcher','team']);Csrf::verify();$this->loads->delete((int)($_POST['id']??0));log_activity('load_deleted','Deleted a load');$this->flash('success','Load deleted successfully.');$this->redirect('/loads');
    }
}
