<?php
declare(strict_types=1);

use App\Core\Registries\MenuRegistry;
use App\Core\Registries\PermissionRegistry;
use App\Core\EventBus;

MenuRegistry::register('cashier', [
    'label_ar'   => 'خزنة العضويات',
    'label_en'   => 'Membership Treasury',
    'icon'       => 'credit-card',
    'route'      => '/cashier',
    'permission' => 'cashier.view_queue',
    'parent'     => null,
    'order'      => 300,
    'children'   => [
        ['label_ar' => 'طابور الدفع',    'label_en' => 'Payment Queue',      'route' => '/cashier',              'permission' => 'cashier.view_queue',          'order' => 1],
        ['label_ar' => 'استلام تسويات',  'label_en' => 'Receive Settlements','route' => '/cashier/settlements',  'permission' => 'cashier.receive_settlement',  'order' => 2],
        ['label_ar' => 'إيداعات البنك',  'label_en' => 'Bank Deposits',      'route' => '/cashier/deposits',     'permission' => 'cashier.manage_deposits',     'order' => 3],
    ],
]);

PermissionRegistry::register('cashier', [
    'cashier.view_queue'          => ['ar' => 'عرض طابور خزنة العضويات',         'en' => 'View Membership Treasury Queue'],
    'cashier.process_payment'     => ['ar' => 'تحصيل دفعة من خزنة العضويات',     'en' => 'Collect Payment from Membership Treasury'],
    'cashier.cancel_request'      => ['ar' => 'إلغاء طلب دفع',                  'en' => 'Cancel Payment Request'],
    'cashier.receive_settlement'  => ['ar' => 'استلام تسوية من خزنة فرعية',      'en' => 'Receive Sub-Treasury Settlement'],
    'cashier.manage_deposits'     => ['ar' => 'إدارة إيداعات البنك',             'en' => 'Manage Bank Deposits'],
    'cashier.confirm_deposit'     => ['ar' => 'تأكيد إيداع بنكي',               'en' => 'Confirm Bank Deposit'],
    'cashier.view_custody'        => ['ar' => 'عرض رصيد عهدة الخزنة',           'en' => 'View Treasury Custody Balance'],
]);

// When a payment is voided, delegate to PaymentLifecycleService for status reversion
EventBus::listen('payment.voided', function (array $data) {
    try {
        $paymentId = (int) ($data['payment_id'] ?? 0);
        $memberId = (int) ($data['member_id'] ?? 0);
        $paymentType = $data['payment_type'] ?? '';

        if ($paymentId <= 0 || $memberId <= 0) return;

        $db = \App\Core\App::getInstance()->db();
        $payment = $db->selectOne("SELECT related_entity_type, related_entity_id FROM payments WHERE id = ?", [$paymentId]);
        $entityType = $payment['related_entity_type'] ?? null;
        $entityId = (int) ($payment['related_entity_id'] ?? 0);

        \App\Modules\Payments\Services\PaymentLifecycleService::onPaymentVoided(
            $paymentId, $memberId, $paymentType, $entityType, $entityId > 0 ? $entityId : null
        );
    } catch (\Throwable $e) {
        \App\Core\Logger::error("payment.voided listener failed: " . $e->getMessage(), ['data' => $data]);
    }
});

// When a payment request is cancelled, delegate to PaymentLifecycleService
EventBus::listen('payment_request.cancelled', function (array $data) {
    try {
        \App\Modules\Payments\Services\PaymentLifecycleService::onPaymentRequestCancelled($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error("payment_request.cancelled listener failed: " . $e->getMessage(), ['data' => $data]);
    }
});

// When a payment request is completed, delegate activation to PaymentLifecycleService
EventBus::listen('payment_request.completed', function (array $data) {
    try {
        $db = \App\Core\App::getInstance()->db();
        $paymentType = $data['payment_type'] ?? '';
        $memberId = (int) ($data['member_id'] ?? 0);
        $paymentId = (int) ($data['payment_id'] ?? 0);
        $requestId = (int) ($data['request_id'] ?? 0);
        $entityType = $data['related_entity_type'] ?? null;
        $entityId = (int) ($data['related_entity_id'] ?? 0);

        if ($memberId <= 0 || $paymentId <= 0) return;

        // Membership activation (membership_fee / down_payment / type-specific fees)
        if (in_array($paymentType, ['membership_fee', 'down_payment', 'foreign_membership_fee', 'sports_membership_fee'], true)) {
            $requestData = [];
            if ($paymentType === 'down_payment' && $requestId > 0) {
                $request = $db->selectOne("SELECT notes FROM payment_requests WHERE id = ?", [$requestId]);
                $notesData = $request && $request['notes'] ? json_decode($request['notes'], true) : [];
                $requestData['installment_months'] = $notesData['installment_months'] ?? 30;
            }

            $result = \App\Modules\Payments\Services\PaymentLifecycleService::onMembershipPaymentCompleted(
                $memberId, $paymentId, $paymentType, $requestData
            );

            if ($result['success'] && empty($result['already_active']) && empty($result['already_pending_cheques'])) {
                $membershipNumber = $result['membership_number'] ?? null;
                if ($paymentType === 'down_payment') {
                    EventBus::dispatch('member.pending_cheques', ['member_id' => $memberId]);
                } else {
                    EventBus::dispatch('member.activated', ['member_id' => $memberId, 'membership_number' => $membershipNumber]);
                }
            }
        }

        // Addition fee — activate the specific dependent
        if ($paymentType === 'addition_fee' && $entityType && $entityId > 0) {
            \App\Modules\Payments\Services\PaymentLifecycleService::onAdditionFeeCompleted(
                $entityType, $entityId, $memberId, $paymentId
            );

            $receiptNumber = $data['receipt_number'] ?? '';
            if ($receiptNumber) {
                $validTables = ['spouses', 'children', 'temporary_members'];
                if (in_array($entityType, $validTables, true)) {
                    $db->update($entityType, ['fee_receipt_number' => $receiptNumber], '`id` = ?', [$entityId]);
                }
            }

            $eventMap = [
                'spouses'          => ['event' => 'spouse.fee_paid',    'key' => 'spouse_id'],
                'children'         => ['event' => 'child.fee_paid',     'key' => 'child_id'],
                'temporary_members'=> ['event' => 'temporary.fee_paid', 'key' => 'temp_id'],
            ];
            if (isset($eventMap[$entityType])) {
                $cfg = $eventMap[$entityType];
                EventBus::dispatch($cfg['event'], [$cfg['key'] => $entityId, 'member_id' => $memberId, 'payment_id' => $paymentId]);
            }
        }

        // Seasonal fee activation
        if ($paymentType === 'seasonal_fee' && $entityType === 'seasonal_memberships' && $entityId > 0) {
            $db->update('seasonal_memberships', [
                'status'     => 'active',
                'updated_at' => date('Y-m-d H:i:s'),
            ], '`id` = ?', [$entityId]);

            $seasonalMember = $db->selectOne("SELECT membership_type, status FROM members WHERE id = ? AND is_archived = 0", [$memberId]);
            if ($seasonalMember && ($seasonalMember['membership_type'] ?? 'working') === 'seasonal' && $seasonalMember['status'] !== 'active') {
                \App\Modules\Members\Services\MembershipPaymentGuard::activateMember($memberId, $paymentId);
                EventBus::dispatch('member.activated', ['member_id' => $memberId]);
            }

            EventBus::dispatch('seasonal.fee_paid', ['seasonal_id' => $entityId, 'member_id' => $memberId, 'payment_id' => $paymentId]);
        }

        // Life-event fees (divorce, death, waiver, separation)
        if ($entityId > 0) {
            $tableMap = [
                'divorce_fee'    => ['table' => 'divorce_cases',    'event' => 'divorce.fee_paid',  'key' => 'case_id'],
                'death_fee'      => ['table' => 'death_cases',      'event' => 'death.fee_paid',    'key' => 'case_id'],
                'waiver_fee'     => ['table' => 'waiver_requests',  'event' => 'waiver.fee_paid',   'key' => 'waiver_id'],
                'separation_fee' => ['table' => 'transfer_requests','event' => 'transfer.fee_paid', 'key' => 'transfer_id'],
            ];
            if (isset($tableMap[$paymentType])) {
                $cfg       = $tableMap[$paymentType];
                $newStatus = 'fee_paid';

                // Death fee for primary_member: skip to pending_form_fill (wife must fill form next)
                if ($paymentType === 'death_fee') {
                    $deathCase = $db->selectOne("SELECT deceased_type FROM death_cases WHERE id = ?", [$entityId]);
                    if ($deathCase && $deathCase['deceased_type'] === 'primary_member') {
                        $newStatus = 'pending_form_fill';
                    }
                }

                $db->update($cfg['table'], [
                    'status'     => $newStatus,
                    'updated_at' => date('Y-m-d H:i:s'),
                ], '`id` = ?', [$entityId]);
                EventBus::dispatch($cfg['event'], [$cfg['key'] => $entityId, 'payment_id' => $paymentId]);

                // Auto-complete separation transfers after payment (no manual button needed)
                if ($paymentType === 'separation_fee') {
                    try {
                        \App\Modules\Transfers\Services\TransferProcessor::execute($entityId);
                    } catch (\Throwable $autoErr) {
                        \App\Core\Logger::error("Auto-complete transfer #{$entityId} failed: " . $autoErr->getMessage());
                    }
                }
            }
        }
    } catch (\Throwable $e) {
        \App\Core\Logger::error("payment_request.completed listener failed: " . $e->getMessage(), ['data' => $data]);
    }
});
