<?php

declare(strict_types=1);

namespace App\Shared\Support;

use App\Core\Auth;
use App\Core\Url;
use App\Shared\Parties\PartyLedgerSupport;
use App\Shared\Schema\PartySchemaSupport;
use App\Shared\Schema\QuotationSchemaSupport;
use PDO;

final class QuotationSupport
{
    public static function nextQuotationNo(PDO $pdo): string
    {
        QuotationSchemaSupport::ensureQuotationsSchema($pdo);

        $prefix = 'QT-' . date('Y') . '-';
        $row = $pdo->query("SELECT quotation_no FROM quotations ORDER BY id DESC LIMIT 1")->fetch();
        $n = 1;
        if ($row && preg_match('/(\d+)$/', (string) ($row['quotation_no'] ?? ''), $m)) {
            $n = ((int) $m[1]) + 1;
        }

        return $prefix . str_pad((string) $n, 5, '0', STR_PAD_LEFT);
    }

    public static function createOrResolveCustomer(PDO $pdo, string $name, string $phone = '', string $email = ''): int
    {
        PartySchemaSupport::ensurePartiesSchema($pdo);

        $name = trim($name);
        $phone = trim($phone);
        $email = trim($email);
        if ($name === '') {
            return 0;
        }

        if ($phone !== '') {
            $st = $pdo->prepare("SELECT id FROM parties WHERE (phone=? OR phone2=?) LIMIT 1");
            $st->execute([$phone, $phone]);
            $id = (int) ($st->fetchColumn() ?: 0);
            if ($id > 0) {
                $pdo->prepare("UPDATE parties SET is_customer=1 WHERE id=?")->execute([$id]);
                return $id;
            }
        }

        $st = $pdo->prepare("SELECT id FROM parties WHERE name=? LIMIT 1");
        $st->execute([$name]);
        $id = (int) ($st->fetchColumn() ?: 0);
        if ($id > 0) {
            $pdo->prepare("UPDATE parties SET is_customer=1 WHERE id=?")->execute([$id]);
            return $id;
        }

        $st = $pdo->prepare("INSERT INTO parties (name,phone,email,is_customer,is_supplier,is_active,created_by) VALUES (?,?,?,?,?,?,?)");
        $st->execute([
            $name,
            $phone !== '' ? $phone : null,
            $email !== '' ? $email : null,
            1,
            0,
            1,
            Auth::id(),
        ]);
        $id = (int) $pdo->lastInsertId();
        PartyLedgerSupport::autoCode($pdo, $id);

        return $id;
    }

    public static function effectivePrice(PDO $pdo, int $partyId, int $itemId, ?string $invoiceDate = null): ?array
    {
        if ($partyId <= 0 || $itemId <= 0) {
            return null;
        }
        QuotationSchemaSupport::ensureQuotationsSchema($pdo);

        $sql = "SELECT q.id quotation_id, q.quotation_no, qi.unit_price, q.quotation_date, q.valid_until\n"
             . "FROM quotations q\n"
             . "JOIN quotation_items qi ON qi.quotation_id=q.id\n"
             . "WHERE q.party_id=? AND qi.item_id=? AND q.status IN ('approved','sent','draft')";
        $params = [$partyId, $itemId];
        if ($invoiceDate) {
            $sql .= " AND q.quotation_date<=? AND (q.valid_until IS NULL OR q.valid_until>=?)";
            $params[] = $invoiceDate;
            $params[] = $invoiceDate;
        }
        $sql .= " ORDER BY q.quotation_date DESC, q.id DESC LIMIT 1";
        $st = $pdo->prepare($sql);
        $st->execute($params);

        $row = $st->fetch();
        return $row ?: null;
    }

    public static function publicPrintUrl(PDO $pdo, int $id, string $format = 'a4'): string
    {
        return Url::to('/prints/quotation?id=' . $id . '&format=' . urlencode($format));
    }

    public static function pdfToken(PDO $pdo, int $id): string
    {
        QuotationSchemaSupport::ensureQuotationsSchema($pdo);
        $st = $pdo->prepare("SELECT quotation_no, updated_at, created_at FROM quotations WHERE id=? LIMIT 1");
        $st->execute([$id]);
        $row = $st->fetch() ?: [];
        $basis = (string)($row['quotation_no'] ?? '') . '|' . (string)($row['updated_at'] ?? $row['created_at'] ?? '');
        $secret = (string)config('app.name', 'SalesStock') . '|' . (string)config('db.name', 'sales_stock_v1');
        return hash_hmac('sha256', $id . '|' . $basis, $secret);
    }

    public static function validatePdfToken(PDO $pdo, int $id, string $token): bool
    {
        if ($id <= 0 || trim($token) === '') {
            return false;
        }
        return hash_equals(self::pdfToken($pdo, $id), trim($token));
    }

    public static function publicPdfUrl(PDO $pdo, int $id): string
    {
        $settings = communication_settings($pdo);
        $base = trim((string)($settings['public_base_url'] ?? ''));
        $path = '/public/quotations/pdf?id=' . $id . '&token=' . self::pdfToken($pdo, $id);
        if ($base !== '') {
            return rtrim($base, '/') . '/quotations/pdf?id=' . $id . '&token=' . self::pdfToken($pdo, $id);
        }

        $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
        $host = (string)($_SERVER['HTTP_HOST'] ?? 'localhost');
        return $scheme . '://' . $host . Url::to('/quotations/pdf?id=' . $id . '&token=' . self::pdfToken($pdo, $id));
    }
}
