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

    public function viewAction($id = 0)
    {
        $m  = new PmServices();
        $pm = $m->find((int)$id);
        if (empty($pm)) { $this->fb('PM not found.'); return; }
        $findings = $m->findingsFor((int)$id);
        $parts    = $m->partsUsedFor((int)$id);
        $photos   = $m->photosFor((int)$id);
        $partsCatalog = (new SpareParts())->list(true);
        $group = strtolower(trim($this->currentUserGroup()));
        $canExecute = in_array($group, ['field supervisor','administrator'], true) && in_array($pm['status'], ['DRAFT','IN_PROGRESS'], true);
        $canReview  = in_array($group, ['projects coordinator','project manager','administrator'], true) && $pm['status'] === 'DONE';
        $canAccept  = in_array($group, ['projects coordinator','project manager','administrator','field supervisor'], true) && in_array($pm['status'], ['DONE','REVIEWED'], true);
        $this->view->setLayout($this->roleLayout());
        $this->view->render('PmServices/view', [
            'page_title'    => 'PM ' . $pm['pm_no'],
            'pm'            => $pm,
            'findings'      => $findings,
            'parts'         => $parts,
            'photos'        => $photos,
            'parts_catalog' => $partsCatalog,
            'can_execute'   => $canExecute,
            'can_review'    => $canReview,
            'can_accept'    => $canAccept,
        ]);
    }

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

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

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

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

    public function reviewAjAction()
    {
        header('Content-Type: application/json');
        try {
            $pmId  = (int)($_POST['pm_id'] ?? 0);
            $notes = (string)($_POST['notes'] ?? '');
            if ($pmId <= 0) throw new InvalidArgumentException('pm_id required.');
            (new PmServices())->review($pmId, $notes, $this->currentUserId(), $_SESSION['full_name'] ?? '');
            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 {
            $pmId = (int)($_POST['pm_id'] ?? 0);
            if ($pmId <= 0) throw new InvalidArgumentException('pm_id required.');
            (new PmServices())->clientAccept(
                $pmId,
                (string)($_POST['client_name'] ?? ''),
                (string)($_POST['signature_path'] ?? ''),
                (string)($_POST['decision'] ?? 'ACCEPTED')
            );
            echo json_encode(['ok' => true]);
        } 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 {
            $pmId = (int)($_POST['pm_id'] ?? 0);
            if ($pmId <= 0) throw new InvalidArgumentException('pm_id required.');
            $file = $_FILES['photo'] ?? null;
            if (!$file || empty($file['tmp_name'])) throw new InvalidArgumentException('No photo uploaded.');
            $id = (new PmServices())->addPhoto(
                $pmId, $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 PmServices())->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 PmServices())->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-7 · Upload a photo/signature directly onto a template item finding.
     * Called when the input_type is PHOTO or SIGNATURE.
     */
    public function saveFindingPhotoAjAction()
    {
        header('Content-Type: application/json');
        try {
            $pmId       = (int)($_POST['pm_id'] ?? 0);
            $itemId     = (int)($_POST['template_item_id'] ?? 0);
            $isSig      = !empty($_POST['is_signature']);
            if ($pmId <= 0 || $itemId <= 0) throw new InvalidArgumentException('pm_id + template_item_id required.');
            $file = $_FILES['photo'] ?? null;
            if (!$file || empty($file['tmp_name'])) throw new InvalidArgumentException('No file uploaded.');
            $rel = (new PmServices())->saveFindingPhoto($pmId, $itemId, $file, $isSig);
            echo json_encode(['ok' => true, 'path' => $rel]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    /** Slice 8S-6 · Raise IMPREST cash request from a PM (adhoc spare needed on site). */
    public function raiseCashRequestAjAction()
    {
        header('Content-Type: application/json');
        try {
            $pmId   = (int)($_POST['pm_id'] ?? 0);
            $amount = (float)($_POST['amount'] ?? 0);
            $reason = trim((string)($_POST['reason'] ?? ''));
            if ($pmId <= 0)  throw new InvalidArgumentException('pm_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.');

            $pm = (new PmServices())->find($pmId);
            if (empty($pm)) throw new RuntimeException('PM not found.');
            $purpose = 'Adhoc spare · PM ' . $pm['pm_no']
                . ' · ' . ($pm['site_name'] ?? '(no site)')
                . ($pm['asset_no'] ? ' · ' . $pm['asset_no'] : '')
                . ' · ' . $reason;

            if (!class_exists('Lpos')) require_once ROOT . '/app/models/Lpos.php';
            $db = new DB();
            $pr = $db->mySelect("SELECT project_id FROM service_contracts WHERE c0d = :c", [':c' => (int)$pm['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' => 'PM Executions',
            'fb_msg'     => '<div class="alert alert-warning">' . htmlspecialchars($msg) . '</div>',
        ]);
    }
}
