<?php
/**
 * CompanyProfile · Slice 8V.
 *
 * Single-row "our company" profile. Field-level RBAC:
 *   CRM         → contact info + trading identity (trading_name, short_name, logo, tagline, addresses, phones, emails, website)
 *   Executive   → legal / tax / bank details (legal_name, reg_no, TIN, VAT, tax regime, bank_*)
 *   Administrator → everything (superset)
 *
 * The view renders every field but disables the ones the current role can't edit;
 * the model enforces the same rule on save so nobody bypasses via a hand-crafted POST.
 */
class CompanyProfile extends Model
{
    /** Fields the CRM group may write. */
    public const CRM_FIELDS = [
        'trading_name','short_name','logo_path','tagline',
        'physical_address','postal_address','region','district',
        'phone_primary','phone_secondary','email_primary','email_secondary','website',
    ];

    /** Fields the Executive group may write (legal/tax + bank). */
    public const EXEC_FIELDS = [
        'legal_name','reg_number','tin','vat_number','tax_regime',
        'bank_name','bank_branch','bank_account_name','bank_account_no','bank_swift','bank_currency',
    ];

    /** Admin owns the union — no explicit list needed, just merge. */
    public static function allFields(): array
    {
        return array_merge(self::CRM_FIELDS, self::EXEC_FIELDS);
    }

    /**
     * Return the set of field names writable by the given user_group_name.
     * Empty = read-only.
     */
    public static function writableFieldsFor(string $group): array
    {
        $g = strtoupper($group);
        return match ($g) {
            'ADMINISTRATOR'                        => self::allFields(),
            'EXECUTIVE'                            => self::EXEC_FIELDS,
            'CRM'                                  => self::CRM_FIELDS,
            default                                => [],
        };
    }

    public function get(): array
    {
        $db = new DB();
        $r = $db->mySelect("SELECT * FROM company_profile WHERE c0d = 1", []);
        if (empty($r)) {
            // Shouldn't happen — schema seeds row 1 — but return sane defaults if the row was deleted manually.
            return [
                'c0d' => 1, 'trading_name' => 'DS Pera', 'short_name' => 'DSP',
                'legal_name' => 'DS Pera Ltd', 'bank_currency' => 'TZS',
            ];
        }
        return $r[0];
    }

    /**
     * Save the row. Only fields writable by $group are applied — any other keys in $d are silently discarded.
     * Returns ['ok' => bool, 'saved' => list<field>, 'ignored' => list<field>, 'msg' => string?].
     */
    public function save(array $d, string $group, int $userId, string $userName): array
    {
        $allowed = self::writableFieldsFor($group);
        if (empty($allowed)) return ['ok' => false, 'msg' => 'Your role cannot edit the company profile.'];

        $current = $this->get();
        $saved = []; $ignored = []; $set = []; $params = [':id' => 1, ':u' => $userId, ':un' => $userName];

        foreach (self::allFields() as $f) {
            if (!array_key_exists($f, $d)) continue;
            if (!in_array($f, $allowed, true)) { $ignored[] = $f; continue; }

            // Basic validation for a couple of fields
            $val = trim((string)$d[$f]);
            if ($f === 'bank_currency') { $val = strtoupper($val); if ($val === '') $val = (string)$current['bank_currency']; if (strlen($val) > 6) $val = substr($val, 0, 6); }
            if ($f === 'website' && $val !== '' && !preg_match('~^https?://~i', $val)) $val = 'https://' . $val;
            if ($f === 'email_primary' || $f === 'email_secondary') {
                if ($val !== '' && !filter_var($val, FILTER_VALIDATE_EMAIL)) {
                    return ['ok' => false, 'msg' => "Invalid email in {$f}."];
                }
            }
            $set[] = "$f = :p_$f";
            $params[":p_$f"] = $val;
            $saved[] = $f;
        }
        if (empty($set)) return ['ok' => true, 'saved' => [], 'ignored' => $ignored, 'msg' => 'Nothing to save.'];

        $db = new DB();
        $db->insertUpdate(
            "UPDATE company_profile SET " . implode(', ', $set) . ",
                edited_by = :u, edited_by_name = :un, edited_on = NOW()
              WHERE c0d = :id",
            $params
        );
        return ['ok' => true, 'saved' => $saved, 'ignored' => $ignored];
    }
}
