<?php
class CalloutsController extends Controller
{
    public function indexAction()
    {
        $status = (string)($_GET['status'] ?? '');
        $rows   = (new Callouts())->list($status);
        $this->view->setLayout($this->roleLayout());
        $this->view->render('Callouts/index', ['page_title' => 'Callouts', 'rows' => $rows, 'status' => $status]);
    }

    public function viewAction($id = 0)
    {
        $m  = new Callouts();
        $co = $m->find((int)$id);
        if (empty($co)) { $this->fb('Callout not found.'); return; }
        $parts  = $m->partsUsedFor((int)$id);
        $photos = $m->photosFor((int)$id);
        $partsCatalog = (new SpareParts())->list(true);
        $group = strtolower(trim($this->currentUserGroup()));
        $canDispatch = in_array($group, ['projects coordinator','project manager','administrator','crm'], true) && $co['status'] === 'OPEN';
        // Slice 8Z-z-G · PC + PM + FS + Admin can now log arrival / findings / resolve.
        $editors     = ['field supervisor','projects coordinator','project manager','administrator'];
        $canArrive   = in_array($group, $editors, true) && $co['status'] === 'DISPATCHED';
        $canResolve  = in_array($group, $editors, true) && in_array($co['status'], ['DISPATCHED','ON_SITE'], true);
        $canFindings = in_array($group, $editors, true) && !in_array($co['status'], ['CLOSED','CANCELLED','CLIENT_ACCEPTED'], true);
        $canAccept   = in_array($group, ['projects coordinator','project manager','administrator'], true) && $co['status'] === 'RESOLVED';
        $canClose    = in_array($group, ['projects coordinator','project manager','administrator'], true) && in_array($co['status'], ['RESOLVED','CLIENT_ACCEPTED'], true);
        // Linked spare requests (8Z-z-D bridge).
        $linkedRequests = $m->linkedSpareRequests((int)$id);
        $this->view->setLayout($this->roleLayout());
        $this->view->render('Callouts/view', [
            'page_title'       => 'Callout ' . $co['callout_no'],
            'co'               => $co,
            'parts'            => $parts,
            'photos'           => $photos,
            'parts_catalog'    => $partsCatalog,
            'linked_requests'  => $linkedRequests,
            'can_dispatch'     => $canDispatch,
            'can_arrive'       => $canArrive,
            'can_resolve'      => $canResolve,
            'can_findings'     => $canFindings,
            'can_accept'       => $canAccept,
            'can_close'        => $canClose,
        ]);
    }

    /* ── Slice 8Z-z-G · Findings / Accept / Close ─────────────────────── */

    public function saveFindingsAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            (new Callouts())->saveFindings($coId, $_POST);
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function clientAcceptAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            $name = (string)($_POST['client_name'] ?? '');
            if (trim($name) === '') throw new InvalidArgumentException('Client name required.');
            $sigPath = null;
            // Optional signature upload — reuses the existing photo route (kind = CLIENT_SIGNATURE).
            if (!empty($_FILES['signature']['tmp_name'])) {
                $photoId = (new Callouts())->addPhoto(
                    $coId, $_FILES['signature'], 'CLIENT_SIGNATURE',
                    'Client signature — ' . $name,
                    $this->currentUserId(), $_SESSION['full_name'] ?? ''
                );
                $ph = (new Callouts())->findPhoto($photoId);
                $sigPath = $ph['file_path'] ?? null;
            }
            (new Callouts())->clientAccept($coId, $name, $sigPath);
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function closeAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            (new Callouts())->close($coId, $this->currentUserId(), (string)($_SESSION['full_name'] ?? ''));
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function saveIntakeAjAction()
    {
        header('Content-Type: application/json');
        try {
            $id = (new Callouts())->saveIntake($_POST, $this->currentUserId(), $_SESSION['full_name'] ?? '');
            echo json_encode(['ok' => true, 'id' => $id]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function dispatchAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            $tech = (int)($_POST['tech_user_id'] ?? $this->currentUserId());
            $name = (string)($_POST['tech_name'] ?? $_SESSION['full_name'] ?? '');
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            (new Callouts())->dispatch($coId, $tech, $name);
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function arriveAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            (new Callouts())->arrive($coId);
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function resolveAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            (new Callouts())->resolve($coId, $_POST);
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function addPartAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            $id = (new Callouts())->addPart($coId, $_POST);
            echo json_encode(['ok' => true, 'id' => $id]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    /* ── Slice 8S-7 · Photo evidence ─────────────────────────────────── */

    public function addPhotoAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId = (int)($_POST['co_id'] ?? 0);
            if ($coId <= 0) throw new InvalidArgumentException('co_id required.');
            $file = $_FILES['photo'] ?? null;
            if (!$file || empty($file['tmp_name'])) throw new InvalidArgumentException('No photo uploaded.');
            $id = (new Callouts())->addPhoto(
                $coId, $file,
                (string)($_POST['kind'] ?? 'OTHER'),
                (string)($_POST['caption'] ?? ''),
                $this->currentUserId(), $_SESSION['full_name'] ?? ''
            );
            echo json_encode(['ok' => true, 'photo_id' => $id]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function removePhotoAjAction()
    {
        header('Content-Type: application/json');
        try {
            $id = (int)($_POST['photo_id'] ?? 0);
            if ($id <= 0) throw new InvalidArgumentException('photo_id required.');
            (new Callouts())->removePhoto($id);
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function photoDownloadAction($id = 0)
    {
        $id = (int)$id;
        if ($id <= 0) { http_response_code(400); echo 'Bad request.'; return; }
        $p = (new Callouts())->findPhoto($id);
        if (empty($p)) { http_response_code(404); echo 'Not found.'; return; }
        $abs = ROOT . '/' . ltrim((string)$p['file_path'], '/');
        if (!is_file($abs)) { http_response_code(404); echo 'File missing.'; return; }
        header('Content-Type: ' . (string)($p['mime'] ?: 'application/octet-stream'));
        header('Content-Length: ' . (int)filesize($abs));
        header('Content-Disposition: inline; filename="' . str_replace('"', '', (string)($p['original_name'] ?: basename($abs))) . '"');
        readfile($abs); exit();
    }

    /**
     * Slice 8S-6 · Raise an adhoc IMPREST cash request from a callout — for the FS to buy
     * a spare on the spot. Pre-fills purpose with callout ref + site + description. Feeds into
     * the existing Lpos cash-out chain (PC approve → Accountant disburse → retirement).
     */
    public function raiseCashRequestAjAction()
    {
        header('Content-Type: application/json');
        try {
            $coId    = (int)($_POST['co_id'] ?? 0);
            $amount  = (float)($_POST['amount'] ?? 0);
            $reason  = trim((string)($_POST['reason'] ?? ''));
            if ($coId <= 0)   throw new InvalidArgumentException('co_id required.');
            if ($amount <= 0) throw new InvalidArgumentException('Amount must be > 0.');
            if ($reason === '') throw new InvalidArgumentException('Reason required.');

            $g = strtolower(trim($this->currentUserGroup()));
            if (!in_array($g, ['field supervisor','projects coordinator','project manager','administrator'], true))
                throw new RuntimeException('Only FS / PC / PM / Admin can raise cash requests.');

            $co = (new Callouts())->find($coId);
            if (empty($co)) throw new RuntimeException('Callout not found.');

            $purpose = 'Adhoc spare · Callout ' . $co['callout_no']
                . ' · ' . ($co['site_name'] ?? '(no site)')
                . ($co['asset_no'] ? ' · ' . $co['asset_no'] : '')
                . ' · ' . $reason;

            if (!class_exists('Lpos')) require_once ROOT . '/app/models/Lpos.php';
            // Find project_id via contract → project
            $db = new DB();
            $pr = $db->mySelect("SELECT project_id FROM service_contracts WHERE c0d = :c", [':c' => (int)$co['contract_id']]);
            $pid = !empty($pr) ? (int)$pr[0]['project_id'] : 0;

            $r = (new Lpos())->create([
                'lpo_type'      => 'IMPREST',
                'amount'        => $amount,
                'currency'      => 'TZS',
                'purpose'       => $purpose,
                'project_id'    => $pid,
                'source_module' => 'services',
                'payee_type'    => 'employee',
                'payee_name'    => $_SESSION['full_name'] ?? '',
            ], $this->currentUserId(), $_SESSION['full_name'] ?? '');
            echo json_encode($r);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    private function fb(string $msg): void
    {
        $this->view->setLayout($this->roleLayout());
        $this->view->render('generals/fb_page', [
            'page_title' => 'Callouts',
            'fb_msg'     => '<div class="alert alert-warning">' . htmlspecialchars($msg) . '</div>',
        ]);
    }
}
