<?php
/**
 * ServiceContractSitePocs · Slice 8Z-z-A.
 *
 * Multiple POCs per client site. Site manager + tech + security is the typical
 * Vodacom shape — the site_contact_name/phone on service_contract_sites was a
 * single-contact carry-over from the previous slice; migration seeded those as
 * is_primary=1, role=SITE_MANAGER rows in this table. UI now writes here.
 */
class ServiceContractSitePocs extends Model
{
    public const ROLES = ['SITE_MANAGER','TECH','SECURITY','OPS','OTHER'];

    /** POCs for one site — primary first, then by role. */
    public function listFor(int $siteId): array
    {
        $db = new DB();
        return $db->mySelect(
            "SELECT * FROM service_contract_site_pocs
              WHERE site_id = :s AND deleted = 0
              ORDER BY is_primary DESC, poc_role, c0d",
            [':s' => $siteId]
        ) ?: [];
    }

    /** POCs for all sites of a contract in one shot — for the drawer refresh. */
    public function listForContract(int $contractId): array
    {
        $db = new DB();
        return $db->mySelect(
            "SELECT p.*
               FROM service_contract_site_pocs p
               JOIN service_contract_sites s ON s.c0d = p.site_id
              WHERE s.contract_id = :c AND p.deleted = 0
              ORDER BY p.site_id, p.is_primary DESC, p.poc_role, p.c0d",
            [':c' => $contractId]
        ) ?: [];
    }

    /**
     * Upsert one POC. When is_primary flips to 1, any other primary POCs on the
     * same site are demoted so exactly one is primary at a time.
     */
    public function save(int $siteId, array $d, int $userId): array
    {
        if ($siteId <= 0) return ['ok' => false, 'msg' => 'site_id required.'];
        $name = trim((string)($d['poc_name'] ?? ''));
        if ($name === '') return ['ok' => false, 'msg' => 'poc_name required.'];
        $role = strtoupper((string)($d['poc_role'] ?? 'OTHER'));
        if (!in_array($role, self::ROLES, true)) $role = 'OTHER';
        $isPrimary = !empty($d['is_primary']) ? 1 : 0;

        $db = new DB();
        $id = (int)($d['c0d'] ?? 0);
        $params = [
            ':s'  => $siteId,
            ':r'  => $role,
            ':n'  => $name,
            ':ph' => trim((string)($d['poc_phone'] ?? '')) ?: null,
            ':em' => trim((string)($d['poc_email'] ?? '')) ?: null,
            ':pr' => $isPrimary,
            ':nt' => trim((string)($d['notes'] ?? '')) ?: null,
        ];

        if ($id > 0) {
            // PDO strict binding — UPDATE SQL doesn't reference :s, so build a fresh param array.
            $u = [
                ':r'  => $params[':r'],
                ':n'  => $params[':n'],
                ':ph' => $params[':ph'],
                ':em' => $params[':em'],
                ':pr' => $params[':pr'],
                ':nt' => $params[':nt'],
                ':id' => $id,
            ];
            $db->insertUpdate(
                "UPDATE service_contract_site_pocs
                    SET poc_role=:r, poc_name=:n, poc_phone=:ph, poc_email=:em,
                        is_primary=:pr, notes=:nt
                  WHERE c0d=:id",
                $u
            );
            if ($isPrimary) $this->demoteOtherPrimaries($siteId, $id);
            return ['ok' => true, 'id' => $id];
        }
        $params[':cb'] = $userId;
        $r = $db->insertUpdate(
            "INSERT INTO service_contract_site_pocs
                (site_id, poc_role, poc_name, poc_phone, poc_email, is_primary, notes, created_by, created_on)
             VALUES (:s, :r, :n, :ph, :em, :pr, :nt, :cb, NOW())",
            $params
        );
        $newId = (int)($r['last_id'] ?? 0);
        if ($isPrimary && $newId > 0) $this->demoteOtherPrimaries($siteId, $newId);
        return ['ok' => true, 'id' => $newId];
    }

    private function demoteOtherPrimaries(int $siteId, int $keepId): void
    {
        (new DB())->insertUpdate(
            "UPDATE service_contract_site_pocs SET is_primary = 0
              WHERE site_id = :s AND c0d <> :k AND is_primary = 1",
            [':s' => $siteId, ':k' => $keepId]
        );
    }

    /** Soft-delete one POC row. */
    public function remove(int $pocId): array
    {
        if ($pocId <= 0) return ['ok' => false, 'msg' => 'poc_id required.'];
        (new DB())->insertUpdate(
            "UPDATE service_contract_site_pocs SET deleted = 1 WHERE c0d = :id",
            [':id' => $pocId]
        );
        return ['ok' => true];
    }

    /**
     * PM/PC stamps that the POC details on a site are verified. Writes to
     * service_contract_sites (not this table) since one site → one confirmation.
     */
    public function confirmSite(int $siteId, int $userId): array
    {
        if ($siteId <= 0) return ['ok' => false, 'msg' => 'site_id required.'];
        (new DB())->insertUpdate(
            "UPDATE service_contract_sites
                SET poc_confirmed_by = :u, poc_confirmed_on = NOW()
              WHERE c0d = :id",
            [':u' => $userId, ':id' => $siteId]
        );
        return ['ok' => true];
    }

    /** Undo confirmation — used when POCs change materially after a stamp. */
    public function unconfirmSite(int $siteId): array
    {
        if ($siteId <= 0) return ['ok' => false, 'msg' => 'site_id required.'];
        (new DB())->insertUpdate(
            "UPDATE service_contract_sites
                SET poc_confirmed_by = NULL, poc_confirmed_on = NULL
              WHERE c0d = :id",
            [':id' => $siteId]
        );
        return ['ok' => true];
    }
}
