<?php

class DriverPortalController extends Controller
{
    private Load $loads;
    private Document $documents;

    public function __construct()
    {
        $this->loads = new Load();
        $this->documents = new Document();
    }

    public function index(): void
    {
        Auth::requireRole(['driver']);
        $user = Auth::user();
        if (empty($user['driver_id'])) {
            $loads = [];
            $missingDriver = true;
        } else {
            $loads = $this->loads->forDriver((int) $user['driver_id']);
            $missingDriver = false;
        }
        $this->view('driver_portal/index', compact('loads', 'missingDriver'));
    }

    public function show(): void
    {
        Auth::requireRole(['driver']);
        $load = $this->authorizedLoad((int) ($_GET['id'] ?? 0));
        $documents = $this->documents->forLoadWithStops((int) $load['id']);
        $events = $this->loads->events((int) $load['id']);
        $locations = $this->loads->latestLocations((int) $load['id']);
        $borderCrossings = (new BorderCrossing())->forLoad((int) $load['id']);
        $temperatureLogs = (new TemperatureLog())->forLoad((int) $load['id']);
        $this->view('driver_portal/show', compact('load', 'documents', 'events', 'locations', 'borderCrossings', 'temperatureLogs'));
    }

    public function status(): void
    {
        Auth::requireRole(['driver']);
        Csrf::verify();
        $load = $this->authorizedLoad((int) ($_POST['id'] ?? 0));

        $allowed = ['arrived_pickup', 'picked_up', 'in_transit', 'arrived_delivery', 'delivered'];
        $status = $_POST['status'] ?? '';
        if (in_array($status, $allowed, true)) {
            $latitude = $this->nullableFloat($_POST['latitude'] ?? null);
            $longitude = $this->nullableFloat($_POST['longitude'] ?? null);
            $this->loads->updateStatus((int) $load['id'], $status, $latitude, $longitude, trim((string) ($_POST['location_address'] ?? '')) ?: null);
            notify_roles(['owner','admin','dispatcher'], 'Driver status update', $load['load_number'] . ' is now ' . readable_status($status) . '.', '/loads/edit?id=' . (int)$load['id'], $status==='delivered'?'success':'info');
            log_activity('driver_status_updated', 'Driver updated load ' . $load['load_number'] . ' to ' . readable_status($status));
            $this->flash('success', 'Load status updated.');
        }
        $this->redirect('/driver/loads/show?id=' . $load['id']);
    }

    public function location(): void
    {
        Auth::requireRole(['driver']);
        Csrf::verify();
        $user = Auth::user();
        $load = $this->authorizedLoad((int) ($_POST['id'] ?? 0));

        $latitude = $this->nullableFloat($_POST['latitude'] ?? null);
        $longitude = $this->nullableFloat($_POST['longitude'] ?? null);
        if ($latitude === null || $longitude === null) {
            $this->flash('danger', 'Location was not captured. Please allow location access and try again.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $this->loads->updateLocation(
            (int) $load['id'],
            (int) $user['driver_id'],
            $latitude,
            $longitude,
            $this->nullableFloat($_POST['accuracy'] ?? null),
            trim((string) ($_POST['location_address'] ?? '')) ?: null,
            $load['status'] ?? null,
            trim((string) ($_POST['notes'] ?? '')) ?: null
        );

        log_activity('driver_location_updated', 'Driver shared location for load ' . $load['load_number']);
        $this->flash('success', 'Location updated successfully.');
        $this->redirect('/driver/loads/show?id=' . $load['id']);
    }

    public function completeStop(): void
    {
        Auth::requireRole(['driver']);
        Csrf::verify();
        $load = $this->authorizedLoad((int) ($_POST['load_id'] ?? 0));
        $stopId = (int) ($_POST['stop_id'] ?? 0);

        if (!$this->loads->stopBelongsToLoad($stopId, (int) $load['id'])) {
            $this->flash('danger', 'Stop not found for this load.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $this->loads->completeStop($stopId, (int) $load['id'], $this->nullableFloat($_POST['latitude'] ?? null), $this->nullableFloat($_POST['longitude'] ?? null));
        log_activity('driver_stop_completed', 'Driver marked a stop complete for load ' . $load['load_number']);
        $this->flash('success', 'Stop marked complete.');
        $this->redirect('/driver/loads/show?id=' . $load['id']);
    }

    public function upload(): void
    {
        Auth::requireRole(['driver']);
        Csrf::verify();
        $load = $this->authorizedLoad((int) ($_POST['load_id'] ?? 0));

        $relatedType = $_POST['related_type'] ?? 'load';
        $relatedId = (int) ($_POST['related_id'] ?? $load['id']);
        if ($relatedType === 'stop' && !$this->loads->stopBelongsToLoad($relatedId, (int) $load['id'])) {
            $this->flash('danger', 'Selected stop is invalid for this load.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }
        if ($relatedType !== 'stop') {
            $relatedType = 'load';
            $relatedId = (int) $load['id'];
        }

        if (empty($_FILES['file']['tmp_name']) || ($_FILES['file']['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
            $this->flash('danger', 'Please choose an image or document to upload.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $file = $_FILES['file'];
        $maxSize = 15 * 1024 * 1024;
        if (($file['size'] ?? 0) > $maxSize) {
            $this->flash('danger', 'File is too large. Maximum allowed size is 15 MB.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $original = basename((string) $file['name']);
        $extension = strtolower(pathinfo($original, PATHINFO_EXTENSION));
        $allowed = ['pdf', 'jpg', 'jpeg', 'png', 'webp', 'gif', 'heic'];
        if (!in_array($extension, $allowed, true)) {
            $this->flash('danger', 'Allowed files: images and PDF.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $folder = storage_path('uploads/driver-loads/' . date('Y/m'));
        if (!is_dir($folder)) {
            mkdir($folder, 0755, true);
        }

        $stored = bin2hex(random_bytes(16)) . '.' . $extension;
        $target = $folder . DIRECTORY_SEPARATOR . $stored;
        if (!move_uploaded_file($file['tmp_name'], $target)) {
            $this->flash('danger', 'Upload failed. Please check storage folder permissions.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $documentType = trim((string) ($_POST['document_type'] ?? 'Load Photo'));
        $relativePath = str_replace(base_path() . DIRECTORY_SEPARATOR, '', $target);
        $latitude = $this->nullableFloat($_POST['latitude'] ?? null);
        $longitude = $this->nullableFloat($_POST['longitude'] ?? null);
        $locationAddress = trim((string) ($_POST['location_address'] ?? '')) ?: null;
        $notes = trim((string) ($_POST['notes'] ?? '')) ?: null;

        $this->documents->create([
            'related_type' => $relatedType,
            'related_id' => $relatedId,
            'document_type' => $documentType,
            'file_name' => $original,
            'stored_name' => $stored,
            'file_path' => $relativePath,
            'mime_type' => $file['type'] ?? null,
            'file_size' => $file['size'] ?? null,
            'expires_at' => null,
            'notes' => $notes,
            'latitude' => $latitude,
            'longitude' => $longitude,
            'location_address' => $locationAddress,
        ]);

        $this->loads->addEvent((int) $load['id'], 'document_uploaded', $documentType . ' uploaded', $latitude, $longitude, $locationAddress);
        notify_roles(['owner','admin','dispatcher'], 'Driver uploaded a document', $load['load_number'] . ' — ' . $documentType, '/loads/edit?id=' . (int)$load['id'], 'info');
        notify_carrier_users((int)($load['carrier_id'] ?? 0), 'Driver uploaded a document', $load['load_number'] . ' — ' . $documentType, '/carrier/loads/show?id=' . (int)$load['id'], 'info');
        log_activity('driver_document_uploaded', 'Driver uploaded ' . $documentType . ' for load ' . $load['load_number']);
        $this->flash('success', $documentType . ' uploaded successfully.');
        $this->redirect('/driver/loads/show?id=' . $load['id']);
    }




    public function recordTemperature(): void
    {
        Auth::requireRole(['driver']);
        Csrf::verify();
        $user = Auth::user();
        $load = $this->authorizedLoad((int) ($_POST['load_id'] ?? 0));

        if (($_POST['temperature'] ?? '') === '' || !is_numeric($_POST['temperature'])) {
            $this->flash('danger', 'Enter a valid temperature reading.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $stopId = !empty($_POST['stop_id']) ? (int) $_POST['stop_id'] : null;
        if ($stopId && !$this->loads->stopBelongsToLoad($stopId, (int) $load['id'])) {
            $this->flash('danger', 'The selected stop does not belong to this load.');
            $this->redirect('/driver/loads/show?id=' . $load['id']);
        }

        $documentId = null;
        if (!empty($_FILES['temperature_photo']['tmp_name']) && ($_FILES['temperature_photo']['error'] ?? UPLOAD_ERR_NO_FILE) === UPLOAD_ERR_OK) {
            $file = $_FILES['temperature_photo'];
            $original = basename((string) $file['name']);
            $extension = strtolower(pathinfo($original, PATHINFO_EXTENSION));
            if (($file['size'] ?? 0) <= 15 * 1024 * 1024 && in_array($extension, ['jpg','jpeg','png','webp','heic','pdf'], true)) {
                $folder = storage_path('uploads/reefer-temperatures/' . date('Y/m'));
                if (!is_dir($folder)) {
                    mkdir($folder, 0755, true);
                }
                $stored = bin2hex(random_bytes(16)) . '.' . $extension;
                $target = $folder . DIRECTORY_SEPARATOR . $stored;
                if (move_uploaded_file($file['tmp_name'], $target)) {
                    $documentId = $this->documents->create([
                        'related_type' => 'load',
                        'related_id' => (int) $load['id'],
                        'document_type' => 'Reefer Temperature Photo',
                        'file_name' => $original,
                        'stored_name' => $stored,
                        'file_path' => str_replace(base_path() . DIRECTORY_SEPARATOR, '', $target),
                        'mime_type' => $file['type'] ?? null,
                        'file_size' => $file['size'] ?? null,
                        'expires_at' => null,
                        'notes' => trim((string) ($_POST['notes'] ?? '')) ?: null,
                        'latitude' => $_POST['latitude'] ?? null,
                        'longitude' => $_POST['longitude'] ?? null,
                        'location_address' => trim((string) ($_POST['location_address'] ?? '')) ?: null,
                    ]);
                }
            }
        }

        (new TemperatureLog())->create([
            'load_id' => (int) $load['id'],
            'trailer_id' => $load['trailer_id'] ?? null,
            'driver_id' => $user['driver_id'] ?? null,
            'stop_id' => $stopId,
            'document_id' => $documentId,
            'temperature' => $_POST['temperature'],
            'temperature_unit' => $_POST['temperature_unit'] ?? ($load['temperature_unit'] ?? 'F'),
            'setpoint' => $_POST['setpoint'] ?? ($load['temperature_setpoint'] ?? null),
            'reefer_mode' => $_POST['reefer_mode'] ?? ($load['reefer_mode'] ?? null),
            'reefer_fuel_level' => $_POST['reefer_fuel_level'] ?? null,
            'pulp_temperature' => $_POST['pulp_temperature'] ?? null,
            'latitude' => $_POST['latitude'] ?? null,
            'longitude' => $_POST['longitude'] ?? null,
            'location_address' => $_POST['location_address'] ?? null,
            'notes' => $_POST['notes'] ?? null,
        ]);

        $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', 'Reefer temperature recorded: ' . $temperature . ($_POST['temperature_unit'] ?? 'F'));
        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('driver_temperature_recorded', 'Driver recorded reefer temperature for load ' . $load['load_number']);
        $this->flash($outsideRange ? 'danger' : 'success', $outsideRange ? 'Temperature saved. It is outside the required range and dispatch was alerted.' : 'Temperature reading saved.');
        $this->redirect('/driver/loads/show?id=' . $load['id']);
    }


    public function expenses(): void
    {
        Auth::requireRole(['driver']);
        $user=Auth::user();
        $accounting=new Accounting();
        $expenses=$accounting->expenses(null,(int)($user['driver_id']??0));
        $categories=$accounting->expenseCategories();
        $loads=!empty($user['driver_id'])?$this->loads->forDriver((int)$user['driver_id']):[];
        $this->view('driver_portal/expenses',compact('expenses','categories','loads'));
    }

    public function storeExpense(): void
    {
        Auth::requireRole(['driver']); Csrf::verify();
        $user=Auth::user(); $_POST['driver_id']=$user['driver_id']??null; $_POST['status']='submitted';
        if((float)($_POST['amount']??0)<=0){$this->flash('danger','Expense amount is required.');$this->redirect('/driver/expenses');}
        $accounting=new Accounting(); $id=$accounting->createExpense($_POST);
        if(!empty($_FILES['receipt']['tmp_name'])&&($_FILES['receipt']['error']??UPLOAD_ERR_NO_FILE)===UPLOAD_ERR_OK){
            $f=$_FILES['receipt'];$original=basename((string)$f['name']);$ext=strtolower(pathinfo($original,PATHINFO_EXTENSION));
            if(in_array($ext,['pdf','jpg','jpeg','png','webp','heic'],true)){$folder=storage_path('uploads/driver-expenses/'.date('Y/m'));if(!is_dir($folder))mkdir($folder,0755,true);$stored=bin2hex(random_bytes(16)).'.'.$ext;$target=$folder.DIRECTORY_SEPARATOR.$stored;if(move_uploaded_file($f['tmp_name'],$target)){$docId=$this->documents->create(['related_type'=>'expense','related_id'=>$id,'document_type'=>'Expense Receipt','file_name'=>$original,'stored_name'=>$stored,'file_path'=>str_replace(base_path().DIRECTORY_SEPARATOR,'',$target),'mime_type'=>$f['type']??null,'file_size'=>$f['size']??null,'expires_at'=>null,'notes'=>$_POST['description']??null,'latitude'=>$_POST['latitude']??null,'longitude'=>$_POST['longitude']??null,'location_address'=>$_POST['location_address']??null]);$accounting->attachExpenseDocument($id,$docId);}}
        }
        notify_roles(['owner','admin','accountant'], 'Driver expense submitted', 'Expense #' . $id . ' is ready for review.', '/accounting/expenses', 'warning');
        log_activity('driver_expense_submitted','Driver submitted expense #'.$id);$this->flash('success','Expense submitted for review.');$this->redirect('/driver/expenses');
    }

    public function finances(): void
    {
        Auth::requireRole(['driver']);$u=Auth::user();$db=Database::connection();$s=$db->prepare('SELECT driver_settlements.*,loads.load_number FROM driver_settlements LEFT JOIN loads ON loads.id=driver_settlements.load_id WHERE driver_settlements.driver_id=? ORDER BY id DESC');$s->execute([(int)($u['driver_id']??0)]);$settlements=$s->fetchAll();$expenses=(new Accounting())->expenses(null,(int)($u['driver_id']??0));$this->view('driver_portal/finances',compact('settlements','expenses'));
    }

    private function authorizedLoad(int $loadId): array
    {
        $user = Auth::user();
        $load = $this->loads->find($loadId);
        if (!$load || (int) $load['driver_id'] !== (int) ($user['driver_id'] ?? 0)) {
            $this->flash('danger', 'Load not found.');
            $this->redirect('/driver/loads');
        }
        return $load;
    }

    private function nullableFloat($value): ?float
    {
        if ($value === null || $value === '') {
            return null;
        }
        return is_numeric($value) ? (float) $value : null;
    }
}
