<?php
/**
 * ServiceContractsController — Slice 8S-2
 */
class ServiceContractsController extends Controller
{
    public function indexAction()
    {
        $status = (string)($_GET['status'] ?? '');
        $rows   = (new ServiceContracts())->list($status);
        $this->view->setLayout($this->roleLayout());
        $this->view->render('ServiceContracts/index', [
            'page_title' => 'Service Contracts',
            'rows'       => $rows,
            'status'     => $status,
        ]);
    }

    public function viewAction($id = 0)
    {
        $id = (int)$id;
        $m  = new ServiceContracts();
        $c  = $m->find($id);
        if (empty($c)) { $this->fb('Contract not found.'); return; }
        $sites    = $m->sitesFor($id);
        $assets   = $m->assetsFor($id);
        $slas     = $m->slasFor($id);
        $schedule = $m->scheduleFor($id);
        $types    = (new AssetTypes())->all(true);
        $cats     = (new CalloutCategories())->all(true);
        $group    = strtolower(trim($this->currentUserGroup()));
        $canEdit  = in_array($group, ['administrator','project manager','projects coordinator'], true);
        $canActivate = $canEdit && $c['status'] === 'DRAFT' && !empty($sites) && !empty($assets);
        $canBill  = $c['status'] === 'ACTIVE' && in_array($group, ['administrator','accountant','finance manager','project manager'], true);

        // Slice 8S-5 · issued invoices for this contract's customer + drafts under 'services'
        $db2 = new DB();
        $billing = $db2->mySelect(
            "SELECT c0d, sale_no, invoice_date, due_date, total, amount_paid, wht_settled_amount, outstanding_amount,
                    invoice_workflow_status, drafted_by_name
               FROM sales
              WHERE source_module = 'services' AND deleted = 0 AND customer_id = :c
              ORDER BY invoice_date DESC LIMIT 24",
            [':c' => (int)$c['customer_id']]
        ) ?: [];

        $this->view->setLayout($this->roleLayout());
        $this->view->render('ServiceContracts/view', [
            'page_title'    => 'Contract ' . $c['contract_no'],
            'contract'      => $c,
            'sites'         => $sites,
            'assets'        => $assets,
            'slas'          => $slas,
            'schedule'      => $schedule,
            'asset_types'   => $types,
            'categories'    => $cats,
            'can_edit'      => $canEdit,
            'can_activate'  => $canActivate,
            'can_bill'      => $canBill,
            'billing_history' => $billing,
        ]);
    }

    public function saveHeaderAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            $id = (new ServiceContracts())->saveHeader($_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 activateAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            (new ServiceContracts())->activate((int)($_POST['id'] ?? 0), $this->currentUserId());
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function saveSiteAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            $id = (new ServiceContracts())->saveSite($_POST);
            echo json_encode(['ok' => true, 'id' => $id]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function deleteSiteAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            (new ServiceContracts())->deleteSite((int)($_POST['id'] ?? 0));
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function saveAssetAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            $id = (new ServiceContracts())->saveAsset($_POST);
            echo json_encode(['ok' => true, 'id' => $id]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function deleteAssetAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            (new ServiceContracts())->deleteAsset((int)($_POST['id'] ?? 0));
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function saveSlaAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            (new ServiceContracts())->saveSla($_POST);
            echo json_encode(['ok' => true]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    public function generateScheduleAjAction()
    {
        header('Content-Type: application/json');
        try { $this->assertRole();
            $r = (new ServiceContracts())->generateSchedule((int)($_POST['id'] ?? 0));
            echo json_encode($r);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    /** Slice 8S-5 · Manually draft a consumption invoice for a given YYYY-MM. */
    public function draftInvoiceAjAction()
    {
        header('Content-Type: application/json');
        try {
            $g = strtolower(trim($this->currentUserGroup()));
            if (!in_array($g, ['administrator','accountant','finance manager','project manager'], true))
                throw new RuntimeException('Only Admin / Accountant / FM / PM can draft service invoices.');
            $cid   = (int)($_POST['id'] ?? 0);
            $year  = (int)($_POST['year']  ?? date('Y'));
            $month = (int)($_POST['month'] ?? date('n'));
            if ($cid <= 0) throw new InvalidArgumentException('contract id required.');
            $r = (new ServiceContracts())->draftConsumptionInvoice(
                $cid, $year, $month, $this->currentUserId(), $_SESSION['full_name'] ?? ''
            );
            echo json_encode($r);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    /**
     * Slice 8S-8 · Download the monthly compliance PDF for a contract-month.
     * URL: /ServiceContracts/reportPdf/{id}?year=YYYY&month=M
     */
    public function reportPdfAction($id = 0)
    {
        $cid = (int)$id;
        if ($cid <= 0) { http_response_code(400); echo 'Bad request.'; return; }
        $year  = (int)($_GET['year']  ?? date('Y'));
        $month = (int)($_GET['month'] ?? date('n'));
        try {
            if (!class_exists('ServiceReports')) require_once ROOT . '/app/models/ServiceReports.php';
            $pdf = (new ServiceReports())->build($cid, $year, $month);
            $fname = 'ServiceReport_' . $cid . '_' . sprintf('%04d-%02d', $year, $month) . '.pdf';
            $pdf->Output('I', $fname);
        } catch (\Throwable $e) {
            http_response_code(500);
            echo 'Could not build report: ' . htmlspecialchars($e->getMessage());
        }
    }

    /** Slice 8S-5 · Preview consumption calc (JSON) without drafting. */
    public function consumptionPreviewAjAction()
    {
        header('Content-Type: application/json');
        try {
            $cid   = (int)($_GET['id'] ?? $_POST['id'] ?? 0);
            $year  = (int)($_GET['year']  ?? $_POST['year']  ?? date('Y'));
            $month = (int)($_GET['month'] ?? $_POST['month'] ?? date('n'));
            if ($cid <= 0) throw new InvalidArgumentException('contract id required.');
            $r = (new ServiceContracts())->calcConsumption($cid, $year, $month);
            echo json_encode(['ok' => true, 'lines' => $r['lines'], 'subtotal' => $r['subtotal'],
                              'currency' => $r['currency'], 'callout_count' => $r['callout_count']]);
        } catch (\Throwable $e) { echo json_encode(['ok' => false, 'msg' => $e->getMessage()]); }
    }

    private function assertRole(): void
    {
        $g = strtolower(trim($this->currentUserGroup()));
        if (!in_array($g, ['administrator','project manager','projects coordinator'], true))
            throw new RuntimeException('Only Admin / PM / PC can edit contracts.');
    }

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