<?php
class TrucksController extends Controller
{
    /* =========================================================
     *  Truck list  · index / paginated / searchable / filterable
     * ========================================================= */
    public function indexAction($page = 1)
    {
        $page    = max(1, (int)$page);
        $perPage = defined('ROWS_PER_PAGE') ? ROWS_PER_PAGE : 20;

        $filters = [
            'q'       => trim((string)($_GET['q']      ?? '')),
            'type_id' => (int)($_GET['type_id']        ?? 0),
            'status'  => trim((string)($_GET['status'] ?? '')),
        ];

        $m      = new Trucks();
        $tm     = new TruckTypes();
        $result = $m->listPaginated($page, $perPage, $filters);

        // Base URL for pagination links preserves the current filter query string.
        $qs = http_build_query(array_filter($filters, fn($v) => $v !== '' && $v !== 0));
        $baseUrl = PROOT . 'Trucks/index/';
        $pg = Pagination::paginate($result['total'], $perPage, $page, $baseUrl);
        $pgHtml = $pg['html'];
        if ($qs && $pgHtml) {
            // append filter query string to every page link
            $pgHtml = preg_replace('~href=\'([^\']+)\'~', "href='$1?" . htmlspecialchars($qs) . "'", $pgHtml);
        }

        $this->view->setLayout($this->roleLayout());
        $this->view->render('Trucks/index', [
            'page_title' => 'Trucks',
            'rows'       => $result['rows'],
            'total'      => $result['total'],
            'page'       => $page,
            'per_page'   => $perPage,
            'filters'    => $filters,
            'types'      => $tm->allActive(),
            'pg_html'    => $pgHtml,
        ]);
    }

    /* =========================================================
     *  Add / Save new truck
     * ========================================================= */
    public function addAction()
    {
        $tm = new TruckTypes();
        $this->view->setLayout($this->roleLayout());
        $this->view->render('Trucks/add', [
            'page_title' => 'Add Truck',
            'types'      => $tm->allActive(),
            'form'       => [],
            'fb_msg'     => '',
        ]);
    }

    public function saveAction()
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            Router::redirect('Trucks/add'); return;
        }
        $m = new Trucks();
        $r = $m->create($_POST, $this->currentUserId());
        if (!$r['ok']) {
            $tm = new TruckTypes();
            $this->view->setLayout($this->roleLayout());
            $this->view->render('Trucks/add', [
                'page_title' => 'Add Truck',
                'types'      => $tm->allActive(),
                'form'       => $_POST,
                'fb_msg'     => '<div class="alert alert-danger">' . htmlspecialchars($r['msg']) . '</div>',
            ]);
            return;
        }
        $_SESSION['flash_tenant_msg']  = 'Truck ' . htmlspecialchars(strtoupper($_POST['reg_no'] ?? '')) . ' added.';
        $_SESSION['flash_tenant_type'] = 'success';
        Router::redirect('Trucks/view/' . $r['id']);
    }

    /* =========================================================
     *  View one truck (details + docs table)
     * ========================================================= */
    public function viewAction($id = 0)
    {
        $m = new Trucks();
        $t = $m->byId((int)$id);
        if (!$t) { $this->notFound('Truck'); return; }

        $dm  = new TruckDocs();
        $dtm = new TruckDocTypes();

        $this->view->setLayout($this->roleLayout());
        $this->view->render('Trucks/view', [
            'page_title'   => $t['reg_no'] . ' · Truck',
            't'            => $t,
            'docs'         => $dm->forTruck((int)$id),
            'doc_types'    => $dtm->allActive(),
            'gps'          => (new GpsDevices())->latestPositionForTruck((int)$id),
            'pm_schedules' => (new TruckPmSchedules())->forTruck((int)$id),
            'pm_events'    => (new PmEvents())->forTruck((int)$id, 10),
            'pm_templates' => (new PmTemplates())->listAll(true),
        ]);
    }

    /* =========================================================
     *  Edit / update existing truck
     * ========================================================= */
    public function editAction($id = 0)
    {
        $m = new Trucks();
        $t = $m->byId((int)$id);
        if (!$t) { $this->notFound('Truck'); return; }

        $tm = new TruckTypes();
        $this->view->setLayout($this->roleLayout());
        $this->view->render('Trucks/edit', [
            'page_title' => 'Edit · ' . $t['reg_no'],
            't'          => $t,
            'types'      => $tm->allActive(),
            'form'       => $t,
            'fb_msg'     => '',
        ]);
    }

    public function updateAction($id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            Router::redirect('Trucks/edit/' . (int)$id); return;
        }
        $m = new Trucks();
        $r = $m->update((int)$id, $_POST, $this->currentUserId());
        if (!$r['ok']) {
            $tm = new TruckTypes();
            $this->view->setLayout($this->roleLayout());
            $this->view->render('Trucks/edit', [
                'page_title' => 'Edit Truck',
                't'          => $m->byId((int)$id),
                'types'      => $tm->allActive(),
                'form'       => $_POST,
                'fb_msg'     => '<div class="alert alert-danger">' . htmlspecialchars($r['msg']) . '</div>',
            ]);
            return;
        }
        $_SESSION['flash_tenant_msg']  = 'Truck updated.';
        $_SESSION['flash_tenant_type'] = 'success';
        Router::redirect('Trucks/view/' . (int)$id);
    }

    /* =========================================================
     *  Soft-delete
     * ========================================================= */
    public function deleteAction($id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            Router::redirect('Trucks/view/' . (int)$id); return;
        }
        $m = new Trucks();
        $m->softDelete((int)$id, $this->currentUserId());
        $_SESSION['flash_tenant_msg']  = 'Truck removed.';
        $_SESSION['flash_tenant_type'] = 'success';
        Router::redirect('Trucks');
    }

    /* =========================================================
     *  Document upload / delete / view
     * ========================================================= */
    public function uploadDocAction($truck_id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            Router::redirect('Trucks/view/' . (int)$truck_id); return;
        }
        $truckId = (int)$truck_id;
        $tm = new Trucks();
        if (!$tm->byId($truckId)) { $this->notFound('Truck'); return; }

        $fileUrl = ''; $fileName = ''; $fileSize = 0;
        if (!empty($_FILES['doc_file']['name']) && $_FILES['doc_file']['error'] === UPLOAD_ERR_OK) {
            $up = $this->handleFileUpload($_FILES['doc_file'], 'truck_' . $truckId);
            if (!$up['ok']) {
                $_SESSION['flash_tenant_msg']  = $up['msg'];
                $_SESSION['flash_tenant_type'] = 'danger';
                Router::redirect('Trucks/view/' . $truckId); return;
            }
            $fileUrl  = $up['url'];
            $fileName = $up['orig_name'];
            $fileSize = $up['size'];
        }

        $dm = new TruckDocs();
        $r  = $dm->create(array_merge($_POST, [
            'truck_id'   => $truckId,
            'file_url'   => $fileUrl,
            'file_name'  => $fileName,
            'file_size'  => $fileSize,
        ]), $this->currentUserId());

        $_SESSION['flash_tenant_msg']  = $r['msg'];
        $_SESSION['flash_tenant_type'] = $r['ok'] ? 'success' : 'danger';
        Router::redirect('Trucks/view/' . $truckId);
    }

    public function deleteDocAction($doc_id = 0)
    {
        $this->verifyCsrf();
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') !== 'POST') {
            Router::redirect('Trucks'); return;
        }
        $dm  = new TruckDocs();
        $doc = $dm->byId((int)$doc_id);
        if (!$doc) { $this->notFound('Document'); return; }
        $dm->softDelete((int)$doc_id, $this->currentUserId());
        $_SESSION['flash_tenant_msg']  = 'Document removed.';
        $_SESSION['flash_tenant_type'] = 'success';
        Router::redirect('Trucks/view/' . (int)$doc['truck_id']);
    }

    /* =========================================================
     *  Helpers
     * ========================================================= */
    private function notFound(string $what): void
    {
        $this->view->setLayout($this->roleLayout());
        $this->view->render('generals/fb_page', [
            'page_title' => 'Not found',
            'fb_msg'     => '<div class="alert alert-danger">' . htmlspecialchars($what) . ' not found.</div>',
        ]);
    }

    /**
     * Validates and stores an uploaded file under uploads/{scope}/.
     * Whitelist by extension AND MIME sniff, random filename, size cap.
     * Never stores the user-supplied filename in the URL.
     */
    private function handleFileUpload(array $file, string $scope): array
    {
        $maxBytes = defined('MAX_UPLOAD_SIZE') ? MAX_UPLOAD_SIZE : (8 * 1024 * 1024);
        if ($file['size'] > $maxBytes) {
            return ['ok' => false, 'msg' => 'File exceeds max size of ' . formatFileSize($maxBytes) . '.'];
        }
        $allowedExt  = ['pdf','jpg','jpeg','png','webp','doc','docx','xls','xlsx'];
        $allowedMime = [
            'application/pdf',
            'image/jpeg','image/png','image/webp',
            'application/msword','application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            'application/vnd.ms-excel','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        ];
        $origName = basename((string)$file['name']);
        $ext      = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
        if (!in_array($ext, $allowedExt, true)) {
            return ['ok' => false, 'msg' => 'File type .' . $ext . ' is not allowed.'];
        }
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mime  = $finfo ? finfo_file($finfo, $file['tmp_name']) : '';
        if ($finfo) finfo_close($finfo);
        if ($mime && !in_array($mime, $allowedMime, true)) {
            return ['ok' => false, 'msg' => 'File content does not match expected type.'];
        }

        $subdir = preg_replace('/[^a-z0-9_]/', '_', strtolower($scope));
        $destDir = UPLOAD_PATH . $subdir;
        if (!is_dir($destDir)) @mkdir($destDir, 0775, true);

        $rand    = bin2hex(random_bytes(8));
        $newName = date('Ymd_His') . '_' . $rand . '.' . $ext;
        $destPath = $destDir . DS . $newName;
        if (!move_uploaded_file($file['tmp_name'], $destPath)) {
            return ['ok' => false, 'msg' => 'Server could not save the uploaded file.'];
        }
        return [
            'ok'        => true,
            'url'       => UPLOAD_URL . $subdir . '/' . $newName,
            'orig_name' => $origName,
            'size'      => (int)$file['size'],
        ];
    }
}
