<?php

declare(strict_types=1);

namespace App\Modules\Sales\Application\Services;

use PDO;

final class SalesDashboardService
{
    public function __construct(private PDO $pdo)
    {
    }

    /** @return array<string,mixed> */
    public function summary(?string $today = null): array
    {
        $today ??= date('Y-m-d');

        $salesAmountExpr = \column_exists($this->pdo, 'sales_invoices', 'grand_total')
            ? 'COALESCE(si.grand_total, si.total, 0)'
            : (\column_exists($this->pdo, 'sales_invoices', 'total') ? 'COALESCE(si.total, 0)' : '0');

        $returnAmountExpr = \column_exists($this->pdo, 'sales_returns', 'total_amount')
            ? 'COALESCE(sr.total_amount, 0)'
            : (\column_exists($this->pdo, 'sales_returns', 'grand_total')
                ? 'COALESCE(sr.grand_total, sr.total, 0)'
                : (\column_exists($this->pdo, 'sales_returns', 'total') ? 'COALESCE(sr.total, 0)' : '0'));

        $salesSummaryAmountExpr = str_replace('si.', '', $salesAmountExpr);
        $returnSummaryAmountExpr = str_replace('sr.', '', $returnAmountExpr);

        $invoicePartyNameExpr = \column_exists($this->pdo, 'sales_invoices', 'customer_name')
            ? "COALESCE(p.name, si.customer_name, 'عميل نقدي')"
            : "COALESCE(p.name, 'عميل نقدي')";

        $returnPartyNameExpr = \column_exists($this->pdo, 'sales_returns', 'customer_name')
            ? "COALESCE(p.name, sr.customer_name, 'عميل')"
            : "COALESCE(p.name, 'عميل')";

        $from = $today . ' 00:00:00';
        $to = date('Y-m-d 00:00:00', strtotime($today . ' +1 day'));

        $stSales = $this->pdo->prepare("SELECT COUNT(*) c, COALESCE(SUM({$salesSummaryAmountExpr}),0) s FROM sales_invoices WHERE invoice_date >= ? AND invoice_date < ? AND (status IS NULL OR status='POSTED')");
        $stSales->execute([$from, $to]);
        $todaySales = $stSales->fetch() ?: ['c' => 0, 's' => 0];

        $itemsCount = (int) (($this->pdo->query("SELECT COUNT(*) c FROM items WHERE is_active=1")->fetch()['c'] ?? 0));
        $lowCount = (int) (($this->pdo->query("SELECT COUNT(*) c FROM stock_balances sb JOIN items i ON i.id=sb.item_id WHERE sb.warehouse_id=1 AND sb.qty < 5")->fetch()['c'] ?? 0));

        $stReturns = $this->pdo->prepare("SELECT COUNT(*) c, COALESCE(SUM({$returnSummaryAmountExpr}),0) s FROM sales_returns WHERE return_date >= ? AND return_date < ?");
        $stReturns->execute([$from, $to]);
        $todayReturns = $stReturns->fetch() ?: ['c' => 0, 's' => 0];

        $draftInvoices = (int) (($this->pdo->query("SELECT COUNT(*) c FROM sales_invoices WHERE COALESCE(status,'draft')='draft'")->fetch()['c'] ?? 0));

        $suspended = $this->suspendedCarts();

        $latestSalesStmt = $this->pdo->query(
            "SELECT si.id, si.invoice_no, si.invoice_date, {$salesAmountExpr} AS grand_total,
                    {$invoicePartyNameExpr} AS party_name, COALESCE(si.status, 'draft') AS status
             FROM sales_invoices si
             LEFT JOIN parties p ON p.id = si.party_id
             ORDER BY si.id DESC
             LIMIT 5"
        );
        $latestSales = $latestSalesStmt->fetchAll() ?: [];

        $latestReturnsStmt = $this->pdo->query(
            "SELECT sr.id, sr.return_no, sr.return_date, {$returnAmountExpr} AS grand_total,
                    {$returnPartyNameExpr} AS party_name
             FROM sales_returns sr
             LEFT JOIN parties p ON p.id = sr.party_id
             ORDER BY sr.id DESC
             LIMIT 5"
        );
        $latestReturns = $latestReturnsStmt->fetchAll() ?: [];

        return [
            'today_sales' => $todaySales,
            'items_count' => $itemsCount,
            'low_count' => $lowCount,
            'today_returns' => $todayReturns,
            'draft_invoices' => $draftInvoices,
            'suspended_count' => $suspended['count'],
            'suspended_preview' => $suspended['preview'],
            'latest_sales' => $latestSales,
            'latest_returns' => $latestReturns,
        ];
    }

    /** @return array{count:int,preview:array<int,array<string,mixed>>} */
    private function suspendedCarts(): array
    {
        $carts = array_values($_SESSION['pos_suspended'] ?? []);
        usort($carts, static function ($a, $b) {
            return strcmp((string) ($b['created_at'] ?? ''), (string) ($a['created_at'] ?? ''));
        });

        return [
            'count' => count($carts),
            'preview' => array_slice($carts, 0, 5),
        ];
    }
}
