<?php
declare(strict_types=1);

namespace App\Modules\Treasury\Services;

use App\Core\App;
use App\Core\EventBus;
use App\Core\Logger;
use App\Modules\Payments\Services\PaymentService;
use App\Modules\Cashier\Services\PaymentRequestService;

final class TreasuryService
{
    public static function getSubTreasury(): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne("SELECT * FROM treasuries WHERE code = 'SUB_SA' AND is_active = 1");
    }

    public static function getMembershipTreasury(): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne("SELECT * FROM treasuries WHERE code = 'SUB_MEM' AND is_active = 1");
    }

    public static function getByCode(string $code): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne("SELECT * FROM treasuries WHERE code = ? AND is_active = 1", [$code]);
    }

    public static function getMainTreasury(): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne("SELECT * FROM treasuries WHERE type = 'main' AND is_active = 1 LIMIT 1");
    }

    public static function find(int $id): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne("SELECT * FROM treasuries WHERE id = ?", [$id]);
    }

    public static function collectPayment(int $sessionId, int $requestId, string $paymentMethod): array
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        $session = $db->selectOne(
            "SELECT * FROM treasury_sessions WHERE id = ? AND status = 'open'",
            [$sessionId]
        );
        if (!$session) {
            return ['success' => false, 'error' => 'لا توجد وردية مفتوحة'];
        }

        $request = $db->selectOne(
            "SELECT * FROM payment_requests WHERE id = ? AND is_voided = 0 AND status IN ('pending','processing')",
            [$requestId]
        );
        if (!$request) {
            return ['success' => false, 'error' => 'طلب الدفع غير موجود أو تم معالجته'];
        }

        $db->query(
            "UPDATE payment_requests SET status = 'processing', updated_at = NOW() WHERE id = ? AND status = 'pending'",
            [$requestId]
        );

        $treasuryId = (int) $session['treasury_id'];

        $paymentResult = PaymentService::processPayment([
            'member_id'           => (int) $request['member_id'],
            'amount'              => (string) $request['amount'],
            'payment_type'        => $request['payment_type'],
            'payment_method'      => $paymentMethod,
            'description'         => $request['description_ar'] ?? '',
            'related_entity_type' => $request['related_entity_type'],
            'related_entity_id'   => $request['related_entity_id'] ? (int) $request['related_entity_id'] : null,
            'currency'            => $request['currency'] ?? 'EGP',
            'treasury_id'         => $treasuryId,
            'session_id'          => $sessionId,
        ]);

        if (!$paymentResult['success']) {
            $db->query("UPDATE payment_requests SET status = 'pending', updated_at = NOW() WHERE id = ?", [$requestId]);
            return $paymentResult;
        }

        $now = date('Y-m-d H:i:s');
        $db->update('payment_requests', [
            'status'         => 'completed',
            'payment_id'     => (int) $paymentResult['payment_id'],
            'receipt_number' => $paymentResult['receipt_number'] ?? null,
            'processed_by'   => $employee ? (int) $employee->id : null,
            'processed_at'   => $now,
            'updated_at'     => $now,
        ], '`id` = ?', [$requestId]);

        if ($paymentMethod === 'cash') {
            CustodyService::recordCollection(
                $treasuryId,
                (int) $session['cashier_id'],
                (string) $request['amount'],
                (int) $paymentResult['payment_id'],
                PaymentRequestService::getPaymentTypeLabel($request['payment_type'])
            );
        }

        $db->query(
            "UPDATE treasury_sessions SET total_collected = total_collected + ?, total_receipts = total_receipts + 1, updated_at = NOW() WHERE id = ?",
            [(string) $request['amount'], $sessionId]
        );

        EventBus::dispatch('payment_request.completed', [
            'request_id'          => $requestId,
            'request_number'      => $request['request_number'],
            'member_id'           => (int) $request['member_id'],
            'payment_type'        => $request['payment_type'],
            'amount'              => $request['amount'],
            'payment_id'          => $paymentResult['payment_id'],
            'receipt_number'      => $paymentResult['receipt_number'] ?? '',
            'related_entity_type' => $request['related_entity_type'] ?? null,
            'related_entity_id'   => $request['related_entity_id'] ?? null,
        ]);

        EventBus::dispatch('treasury.payment.collected', [
            'payment_id'     => $paymentResult['payment_id'],
            'treasury_id'    => $treasuryId,
            'session_id'     => $sessionId,
            'cashier_id'     => (int) $session['cashier_id'],
            'amount'         => (string) $request['amount'],
            'receipt_number' => $paymentResult['receipt_number'] ?? '',
        ]);

        Logger::info("Treasury payment collected", [
            'payment_id' => $paymentResult['payment_id'],
            'session' => $sessionId,
            'amount' => $request['amount'],
        ]);

        return [
            'success'        => true,
            'payment_id'     => $paymentResult['payment_id'],
            'receipt_id'     => $paymentResult['receipt_id'] ?? null,
            'receipt_number' => $paymentResult['receipt_number'] ?? '',
        ];
    }

    public static function createAndCollectPayment(int $sessionId, array $data, string $paymentMethod): array
    {
        $requestResult = PaymentRequestService::createRequest($data);
        if (!$requestResult['success']) {
            return $requestResult;
        }

        return self::collectPayment($sessionId, (int) $requestResult['request_id'], $paymentMethod);
    }

    public static function getQueueForTreasury(int $treasuryId, array $filters = []): array
    {
        $db = App::getInstance()->db();
        $treasury = self::find($treasuryId);
        if (!$treasury) {
            return [];
        }

        $where = "pr.is_voided = 0";
        $params = [];

        $status = $filters['status'] ?? '';
        if ($status !== '') {
            $where .= ' AND pr.status = ?';
            $params[] = $status;
        } else {
            $where .= " AND pr.status IN ('pending','processing')";
        }

        if ($treasury['code'] === 'SUB_SA') {
            $where .= " AND pr.payment_type IN ('activity_subscription','hourly_booking','sports_registration','sa_form_fee','sa_subscription','sports_subscription','sa_registration_fee')";
        } elseif ($treasury['code'] === 'SUB_MEM') {
            $where .= " AND pr.payment_type IN ('form_fee','membership_fee','down_payment','addition_fee','annual_subscription','divorce_fee','death_fee','waiver_fee','separation_fee','fine','carnet_replacement','seasonal_fee','foreign_membership_fee','sports_membership_fee')";
        }

        $search = trim($filters['search'] ?? '');
        if ($search !== '') {
            $where .= ' AND (m.full_name_ar LIKE ? OR m.form_number LIKE ? OR pr.request_number LIKE ? OR pr.description_ar LIKE ?)';
            $term = '%' . $search . '%';
            $params = array_merge($params, [$term, $term, $term, $term]);
        }

        return $db->select(
            "SELECT pr.*, m.full_name_ar as member_name, m.form_number,
                    e.full_name_ar as requested_by_name
             FROM payment_requests pr
             LEFT JOIN members m ON m.id = pr.member_id
             LEFT JOIN employees e ON e.id = pr.requested_by
             WHERE {$where}
             ORDER BY pr.created_at ASC
             LIMIT 200",
            $params
        );
    }

    public static function getDashboardStats(int $treasuryId, int $cashierId): array
    {
        $db = App::getInstance()->db();

        $currentSession = SessionService::getCurrentSession($treasuryId, $cashierId);
        $custodyBalance = CustodyService::getCurrentBalance($treasuryId, $cashierId);

        $todayCollections = $db->selectOne(
            "SELECT COALESCE(SUM(p.amount), 0) as total, COUNT(*) as count
             FROM payments p
             WHERE p.treasury_id = ? AND p.is_voided = 0 AND DATE(p.payment_date) = CURDATE()",
            [$treasuryId]
        );

        $pendingSettlements = $db->selectOne(
            "SELECT COUNT(*) as count FROM treasury_settlements WHERE from_treasury_id = ? AND status = 'pending'",
            [$treasuryId]
        );

        $treasury = self::find($treasuryId);
        $typeFilter = "('activity_subscription','hourly_booking','sports_registration')";
        if ($treasury && $treasury['code'] === 'SUB_MEM') {
            $typeFilter = "('form_fee','membership_fee','down_payment','addition_fee','annual_subscription','divorce_fee','death_fee','waiver_fee','separation_fee','fine','carnet_replacement','seasonal_fee')";
        }

        $pendingQueue = $db->selectOne(
            "SELECT COUNT(*) as count FROM payment_requests WHERE status IN ('pending','processing') AND is_voided = 0 AND payment_type IN {$typeFilter}"
        );

        return [
            'current_session'     => $currentSession,
            'custody_balance'     => $custodyBalance,
            'today_total'         => (string) ($todayCollections['total'] ?? '0.00'),
            'today_count'         => (int) ($todayCollections['count'] ?? 0),
            'pending_settlements' => (int) ($pendingSettlements['count'] ?? 0),
            'pending_queue'       => (int) ($pendingQueue['count'] ?? 0),
        ];
    }
}
