<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Services\Reports;

use App\Core\App;
use App\Core\Database;
use App\Modules\Accounting\Models\FiscalYear;

final class RevenueAnalysisService
{
    private Database $db;

    public function __construct(?Database $db = null)
    {
        $this->db = $db ?? App::getInstance()->db();
    }

    public function generate(array $filters): array
    {
        $currentFY = FiscalYear::current();
        $dateFrom = $filters['date_from'] ?? ($currentFY ? $currentFY->start_date : date('Y-01-01'));
        $dateTo = $filters['date_to'] ?? date('Y-m-d');
        $branchId = !empty($filters['branch_id']) ? (int) $filters['branch_id'] : null;

        $branchWhere = '';
        $params = [$dateFrom, $dateTo];
        if ($branchId !== null) {
            $branchWhere = ' AND m.branch_id = ?';
            $params[] = $branchId;
        }

        $byType = $this->db->select(
            "SELECT p.payment_type, COALESCE(SUM(p.amount), 0) as total, COUNT(*) as cnt
             FROM payments p
             LEFT JOIN members m ON m.id = p.member_id
             WHERE p.payment_date >= ? AND p.payment_date <= ? AND p.is_voided = 0 {$branchWhere}
             GROUP BY p.payment_type ORDER BY total DESC",
            $params
        );

        $byMethod = $this->db->select(
            "SELECT p.payment_method, COALESCE(SUM(p.amount), 0) as total, COUNT(*) as cnt
             FROM payments p
             LEFT JOIN members m ON m.id = p.member_id
             WHERE p.payment_date >= ? AND p.payment_date <= ? AND p.is_voided = 0 {$branchWhere}
             GROUP BY p.payment_method ORDER BY total DESC",
            $params
        );

        $monthly = $this->db->select(
            "SELECT DATE_FORMAT(p.payment_date, '%Y-%m') as month,
                    COALESCE(SUM(p.amount), 0) as total, COUNT(*) as cnt
             FROM payments p
             LEFT JOIN members m ON m.id = p.member_id
             WHERE p.payment_date >= ? AND p.payment_date <= ? AND p.is_voided = 0 {$branchWhere}
             GROUP BY month ORDER BY month ASC",
            $params
        );

        $monthStart = date('Y-m-01');
        $dailyParams = [$monthStart, date('Y-m-d')];
        $dailyBranchWhere = '';
        if ($branchId !== null) {
            $dailyBranchWhere = ' AND m.branch_id = ?';
            $dailyParams[] = $branchId;
        }
        $daily = $this->db->select(
            "SELECT p.payment_date as day, COALESCE(SUM(p.amount), 0) as total, COUNT(*) as cnt
             FROM payments p
             LEFT JOIN members m ON m.id = p.member_id
             WHERE p.payment_date >= ? AND p.payment_date <= ? AND p.is_voided = 0 {$dailyBranchWhere}
             GROUP BY p.payment_date ORDER BY p.payment_date ASC",
            $dailyParams
        );

        $grandTotal = '0.00';
        $grandCount = 0;
        foreach ($byType as $t) {
            $grandTotal = bcadd($grandTotal, (string) $t['total'], 2);
            $grandCount += (int) $t['cnt'];
        }

        $byBranch = [];
        if ($branchId === null) {
            $byBranch = $this->db->select(
                "SELECT COALESCE(b.name_ar, 'بدون فرع') as branch_name, b.id as branch_id,
                        COALESCE(SUM(p.amount), 0) as total, COUNT(*) as cnt
                 FROM payments p
                 LEFT JOIN members m ON m.id = p.member_id
                 LEFT JOIN branches b ON b.id = m.branch_id
                 WHERE p.payment_date >= ? AND p.payment_date <= ? AND p.is_voided = 0
                 GROUP BY b.id, b.name_ar ORDER BY total DESC",
                [$dateFrom, $dateTo]
            );
        }

        $voidedParams = [$dateFrom, $dateTo];
        if ($branchId !== null) {
            $voidedParams[] = $branchId;
        }
        $voidedRow = $this->db->selectOne(
            "SELECT COALESCE(SUM(p.amount), 0) as total, COUNT(*) as cnt
             FROM payments p
             LEFT JOIN members m ON m.id = p.member_id
             WHERE p.payment_date >= ? AND p.payment_date <= ? AND p.is_voided = 1" .
            ($branchId !== null ? ' AND m.branch_id = ?' : ''),
            $voidedParams
        );

        $branches = $this->db->select("SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar");

        return [
            'by_type'      => $byType,
            'by_method'    => $byMethod,
            'by_branch'    => $byBranch,
            'monthly'      => $monthly,
            'daily'        => $daily,
            'grand_total'  => $grandTotal,
            'grand_count'  => $grandCount,
            'voided_total' => $voidedRow['total'] ?? '0.00',
            'voided_count' => (int) ($voidedRow['cnt'] ?? 0),
            'branches'     => $branches,
        ];
    }
}
