<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Services\Reports;

use App\Core\App;
use App\Core\Database;

final class TreasuryReportService
{
    private Database $db;

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

    public function generate(array $filters): array
    {
        $dateFrom = $filters['date_from'] ?? date('Y-m-01');
        $dateTo = $filters['date_to'] ?? date('Y-m-d');
        $paymentType = $filters['payment_type'] ?? '';
        $paymentMethod = $filters['payment_method'] ?? '';
        $search = trim($filters['search'] ?? '');
        $voidedFilter = $filters['voided'] ?? '0';

        $where = 'p.payment_date >= ? AND p.payment_date <= ?';
        $params = [$dateFrom, $dateTo];

        if ($voidedFilter === '0') {
            $where .= ' AND p.is_voided = 0';
        } elseif ($voidedFilter === '1') {
            $where .= ' AND p.is_voided = 1';
        }

        if ($paymentType !== '') {
            $where .= ' AND p.payment_type = ?';
            $params[] = $paymentType;
        }

        if ($paymentMethod !== '') {
            $where .= ' AND p.payment_method = ?';
            $params[] = $paymentMethod;
        }

        if ($search !== '') {
            $where .= ' AND (m.full_name_ar LIKE ? OR m.form_number LIKE ? OR r.receipt_number LIKE ? OR p.notes LIKE ?)';
            $searchTerm = '%' . $search . '%';
            $params = array_merge($params, [$searchTerm, $searchTerm, $searchTerm, $searchTerm]);
        }

        $totalsRow = $this->db->selectOne(
            "SELECT COALESCE(SUM(p.amount), 0) as total_amount, COUNT(*) as total_count
             FROM payments p
             LEFT JOIN members m ON m.id = p.member_id
             LEFT JOIN receipts r ON r.id = p.receipt_id
             WHERE {$where}",
            $params
        );

        $page = max(1, (int) ($filters['page'] ?? 1));
        $perPage = 50;
        $offset = ($page - 1) * $perPage;
        $totalCount = (int) ($totalsRow['total_count'] ?? 0);
        $totalPages = max(1, (int) ceil($totalCount / $perPage));

        $payments = $this->db->select(
            "SELECT p.*, r.receipt_number, m.full_name_ar as member_name, m.form_number,
                    e.full_name_ar as received_by_name
             FROM payments p
             LEFT JOIN receipts r ON r.id = p.receipt_id
             LEFT JOIN members m ON m.id = p.member_id
             LEFT JOIN employees e ON e.id = p.received_by_employee_id
             WHERE {$where}
             ORDER BY p.id DESC
             LIMIT {$perPage} OFFSET {$offset}",
            $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
             LEFT JOIN receipts r ON r.id = p.receipt_id
             WHERE {$where}
             GROUP BY p.payment_method ORDER BY total DESC",
            $params
        );

        $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
             LEFT JOIN receipts r ON r.id = p.receipt_id
             WHERE {$where}
             GROUP BY p.payment_type ORDER BY total DESC",
            $params
        );

        return [
            'payments'      => $payments,
            'total_amount'  => $totalsRow['total_amount'] ?? '0.00',
            'total_count'   => $totalCount,
            'by_method'     => $byMethod,
            'by_type'       => $byType,
            'page'          => $page,
            'total_pages'   => $totalPages,
        ];
    }
}
