<?php
declare(strict_types=1);

use App\Core\Registries\MenuRegistry;
use App\Core\Registries\PermissionRegistry;
use App\Core\EventBus;
use App\Modules\Accounting\Services\AccountingIntegrationService;

// ────────────────────────────────────────────────────────────
// Accounting Module — Permissions (28 total)
// ────────────────────────────────────────────────────────────

PermissionRegistry::register('accounting', [
    // Dashboard & Reports
    'accounting.reports.view'              => ['ar' => 'لوحة تحكم المحاسبة',            'en' => 'Accounting Dashboard'],
    'accounting.reports.trial_balance'     => ['ar' => 'ميزان المراجعة',                'en' => 'Trial Balance'],
    'accounting.reports.general_ledger'    => ['ar' => 'دفتر الأستاذ العام',            'en' => 'General Ledger'],
    'accounting.reports.income_statement'  => ['ar' => 'قائمة الدخل',                   'en' => 'Income Statement'],
    'accounting.reports.balance_sheet'     => ['ar' => 'الميزانية العمومية',             'en' => 'Balance Sheet'],
    'accounting.reports.consolidated'      => ['ar' => 'ميزانية موحدة',                 'en' => 'Consolidated Balance Sheet'],
    'accounting.reports.ar'                => ['ar' => 'تقرير المدينين',                'en' => 'Accounts Receivable Report'],
    'accounting.reports.ap'                => ['ar' => 'تقرير الدائنين',                'en' => 'Accounts Payable Report'],
    'accounting.reports.member_statement'  => ['ar' => 'كشف حساب عضو',                 'en' => 'Member Statement'],
    'accounting.reports.treasury'          => ['ar' => 'تقرير الخزينة والمدفوعات',      'en' => 'Treasury & Payments Report'],
    'accounting.reports.revenue_analysis'  => ['ar' => 'تحليل الإيرادات',               'en' => 'Revenue Analysis'],

    // Fiscal Year
    'accounting.fiscal_year.view'          => ['ar' => 'عرض السنوات المالية',            'en' => 'View Fiscal Years'],
    'accounting.fiscal_year.manage'        => ['ar' => 'إدارة السنوات المالية',           'en' => 'Manage Fiscal Years'],
    'accounting.fiscal_year.close'         => ['ar' => 'إقفال السنة المالية',            'en' => 'Close Fiscal Year'],

    // Chart of Accounts
    'accounting.coa.view'                  => ['ar' => 'عرض دليل الحسابات',              'en' => 'View Chart of Accounts'],
    'accounting.coa.manage'                => ['ar' => 'إدارة دليل الحسابات',             'en' => 'Manage Chart of Accounts'],

    // Cost Centers
    'accounting.cost_center.view'          => ['ar' => 'عرض مراكز التكلفة',              'en' => 'View Cost Centers'],
    'accounting.cost_center.manage'        => ['ar' => 'إدارة مراكز التكلفة',             'en' => 'Manage Cost Centers'],

    // Bank Accounts
    'accounting.bank_account.view'         => ['ar' => 'عرض الحسابات البنكية',           'en' => 'View Bank Accounts'],
    'accounting.bank_account.manage'       => ['ar' => 'إدارة الحسابات البنكية',          'en' => 'Manage Bank Accounts'],

    // Journal Entries
    'accounting.journal.view'              => ['ar' => 'عرض قيود اليومية',               'en' => 'View Journal Entries'],
    'accounting.journal.create'            => ['ar' => 'إنشاء قيد يومية',                'en' => 'Create Journal Entry'],
    'accounting.journal.post'              => ['ar' => 'ترحيل قيود اليومية',             'en' => 'Post Journal Entries'],
    'accounting.journal.reverse'           => ['ar' => 'عكس قيود اليومية',               'en' => 'Reverse Journal Entries'],

    // Bank Reconciliation
    'accounting.bank_recon.view'           => ['ar' => 'عرض المطابقات البنكية',          'en' => 'View Bank Reconciliations'],
    'accounting.bank_recon.manage'         => ['ar' => 'إدارة المطابقات البنكية',         'en' => 'Manage Bank Reconciliations'],

    // Period Closing
    'accounting.period.view'               => ['ar' => 'عرض إقفال الفترات',              'en' => 'View Period Closings'],
    'accounting.period.close'              => ['ar' => 'إقفال فترة',                     'en' => 'Close Period'],
    'accounting.period.reopen'             => ['ar' => 'إعادة فتح فترة مغلقة',           'en' => 'Reopen Closed Period'],
]);

// ────────────────────────────────────────────────────────────
// Accounting Module — Sidebar Menu
// ────────────────────────────────────────────────────────────

MenuRegistry::register('accounting', [
    'label_ar'   => 'المحاسبة والدفتر العام',
    'label_en'   => 'Accounting & GL',
    'icon'       => 'calculator',
    'route'      => '/accounting',
    'permission' => 'accounting.reports.view',
    'parent'     => null,
    'order'      => 400,
    'children'   => [
        ['label_ar' => 'لوحة التحكم',           'label_en' => 'Dashboard',              'route' => '/accounting',                                    'permission' => 'accounting.reports.view',            'order' => 1],
        ['label_ar' => 'دليل الحسابات',          'label_en' => 'Chart of Accounts',      'route' => '/accounting/chart-of-accounts',                  'permission' => 'accounting.coa.view',                'order' => 2],
        ['label_ar' => 'قيود اليومية',           'label_en' => 'Journal Entries',        'route' => '/accounting/journal-entries',                     'permission' => 'accounting.journal.view',            'order' => 3],
        ['label_ar' => 'السنوات المالية',         'label_en' => 'Fiscal Years',           'route' => '/accounting/fiscal-years',                       'permission' => 'accounting.fiscal_year.view',        'order' => 4],
        ['label_ar' => 'مراكز التكلفة',          'label_en' => 'Cost Centers',           'route' => '/accounting/cost-centers',                       'permission' => 'accounting.cost_center.view',        'order' => 5],
        ['label_ar' => 'الحسابات البنكية',       'label_en' => 'Bank Accounts',          'route' => '/accounting/bank-accounts',                      'permission' => 'accounting.bank_account.view',       'order' => 6],
        ['label_ar' => 'المطابقة البنكية',       'label_en' => 'Bank Reconciliation',    'route' => '/accounting/bank-reconciliation',                'permission' => 'accounting.bank_recon.view',         'order' => 7],
        ['label_ar' => 'إقفال الفترات',          'label_en' => 'Period Closing',         'route' => '/accounting/period-closing',                     'permission' => 'accounting.period.view',             'order' => 8],
        ['label_ar' => 'ميزان المراجعة',         'label_en' => 'Trial Balance',          'route' => '/accounting/reports/trial-balance',              'permission' => 'accounting.reports.trial_balance',   'order' => 9],
        ['label_ar' => 'دفتر الأستاذ',           'label_en' => 'General Ledger',         'route' => '/accounting/reports/general-ledger',             'permission' => 'accounting.reports.general_ledger',  'order' => 10],
        ['label_ar' => 'قائمة الدخل',            'label_en' => 'Income Statement',       'route' => '/accounting/reports/income-statement',           'permission' => 'accounting.reports.income_statement','order' => 11],
        ['label_ar' => 'الميزانية العمومية',      'label_en' => 'Balance Sheet',          'route' => '/accounting/reports/balance-sheet',              'permission' => 'accounting.reports.balance_sheet',   'order' => 12],
        ['label_ar' => 'ميزانية موحدة',          'label_en' => 'Consolidated BS',        'route' => '/accounting/reports/consolidated-balance-sheet', 'permission' => 'accounting.reports.consolidated',    'order' => 13],
        ['label_ar' => 'المدينون (AR)',           'label_en' => 'Accounts Receivable',    'route' => '/accounting/reports/accounts-receivable',        'permission' => 'accounting.reports.ar',              'order' => 14],
        ['label_ar' => 'الدائنون (AP)',           'label_en' => 'Accounts Payable',       'route' => '/accounting/reports/accounts-payable',           'permission' => 'accounting.reports.ap',              'order' => 15],
        ['label_ar' => 'كشف حساب عضو',           'label_en' => 'Member Statement',       'route' => '/accounting/reports/member-statement',           'permission' => 'accounting.reports.member_statement','order' => 16],
        ['label_ar' => 'الخزينة والمدفوعات',     'label_en' => 'Treasury & Payments',    'route' => '/accounting/reports/treasury',                    'permission' => 'accounting.reports.treasury',        'order' => 17],
        ['label_ar' => 'تحليل الإيرادات',        'label_en' => 'Revenue Analysis',       'route' => '/accounting/reports/revenue-analysis',            'permission' => 'accounting.reports.revenue_analysis','order' => 18],
    ],
]);

// ────────────────────────────────────────────────────────────
// Accounting Module — Auto-Create Fiscal Year
// ────────────────────────────────────────────────────────────
// Without an open fiscal year, ALL auto-posted journal entries silently fail.
// This ensures a fiscal year always exists for the current calendar year.
(function (): void {
    try {
        $db = \App\Core\App::getInstance()->db();
        $year = (int) date('Y');
        $startDate = $year . '-01-01';
        $endDate = $year . '-12-31';
        $existing = $db->selectOne(
            "SELECT id FROM fiscal_years WHERE start_date <= ? AND end_date >= ? AND is_archived = 0",
            [$startDate, $endDate]
        );
        if (!$existing) {
            $db->insert('fiscal_years', [
                'name_ar'     => 'السنة المالية ' . $year,
                'name_en'     => 'Fiscal Year ' . $year,
                'start_date'  => $startDate,
                'end_date'    => $endDate,
                'status'      => 'open',
                'is_current'  => 1,
                'is_archived' => 0,
                'created_at'  => date('Y-m-d H:i:s'),
                'updated_at'  => date('Y-m-d H:i:s'),
            ]);
        }
    } catch (\Throwable $e) {
        // Silently ignore — table might not exist yet during initial migration
    }
})();

// ────────────────────────────────────────────────────────────
// Accounting Module — Event Listeners (Auto-Posting)
// ────────────────────────────────────────────────────────────

// ── Payments ─────────────────────────────────────────────────
// When a payment is completed, auto-post journal entry: Dr. Cash/Bank, Cr. Revenue
EventBus::listen('payment.completed', function (array $data): void {
    try {
        AccountingIntegrationService::onPaymentCompleted($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (payment.completed): ' . $e->getMessage());
    }
}, 50); // Priority 50 — runs after Payments module's own listener (100)

// When a payment is voided, reverse the journal entry
EventBus::listen('payment.voided', function (array $data): void {
    try {
        AccountingIntegrationService::onPaymentVoided($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-reverse failed (payment.voided): ' . $e->getMessage());
    }
}, 50);

// ── Sales ────────────────────────────────────────────────────
// When a sale is completed, auto-post COGS entry
EventBus::listen('sale.completed', function (array $data): void {
    try {
        AccountingIntegrationService::onSaleCompleted($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (sale.completed): ' . $e->getMessage());
    }
}, 50);

// When a sale is voided, reverse COGS entry
EventBus::listen('sale.voided', function (array $data): void {
    try {
        AccountingIntegrationService::onSaleVoided($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-reverse failed (sale.voided): ' . $e->getMessage());
    }
}, 50);

// ── HR Payroll ───────────────────────────────────────────────
// When payroll is paid, auto-post salary journal
EventBus::listen('hr.payroll.paid', function (array $data): void {
    try {
        AccountingIntegrationService::onPayrollPaid($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (hr.payroll.paid): ' . $e->getMessage());
    }
}, 50);

// ── Subscriptions ────────────────────────────────────────────
// When a subscription is paid, update AR
EventBus::listen('subscription.paid', function (array $data): void {
    try {
        AccountingIntegrationService::onSubscriptionPaid($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (subscription.paid): ' . $e->getMessage());
    }
}, 50);

// ── Fines ────────────────────────────────────────────────────
// When a fine is imposed, create AR entry and journal
EventBus::listen('fine.imposed', function (array $data): void {
    try {
        AccountingIntegrationService::onFineImposed($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (fine.imposed): ' . $e->getMessage());
    }
}, 50);

// When a fine is collected, update AR
EventBus::listen('fine.paid', function (array $data): void {
    try {
        AccountingIntegrationService::onFineCollected($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (fine.paid): ' . $e->getMessage());
    }
}, 50);

// ── Installments ─────────────────────────────────────────────
// When an installment plan is created, create AR entry
EventBus::listen('installment.plan_created', function (array $data): void {
    try {
        AccountingIntegrationService::onInstallmentPlanCreated($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (installment.plan_created): ' . $e->getMessage());
    }
}, 50);

// When an installment is paid, update AR
EventBus::listen('installment.paid', function (array $data): void {
    try {
        AccountingIntegrationService::onInstallmentPaid($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (installment.paid): ' . $e->getMessage());
    }
}, 50);

// ── Refunds ─────────────────────────────────────────────────
// When a sale is refunded, post reversal GL entry
EventBus::listen('sale.refunded', function (array $data): void {
    try {
        AccountingIntegrationService::onSaleRefunded($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (sale.refunded): ' . $e->getMessage());
    }
}, 50);

// ── Procurement ─────────────────────────────────────────────
// When a vendor invoice is approved, post AP accrual
EventBus::listen('procurement.invoice_approved', function (array $data): void {
    try {
        AccountingIntegrationService::onVendorInvoiceApproved($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (procurement.invoice_approved): ' . $e->getMessage());
    }
}, 50);

// When a vendor payment is completed, post AP reduction
EventBus::listen('procurement.payment_completed', function (array $data): void {
    try {
        AccountingIntegrationService::onVendorPaymentCompleted($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (procurement.payment_completed): ' . $e->getMessage());
    }
}, 50);

// When a vendor payment is voided, reverse the journal entry
EventBus::listen('procurement.payment_voided', function (array $data): void {
    try {
        AccountingIntegrationService::onVendorPaymentVoided($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-reverse failed (procurement.payment_voided): ' . $e->getMessage());
    }
}, 50);

// When a return-to-vendor is completed, post AP debit / inventory credit
EventBus::listen('procurement.rtv_completed', function (array $data): void {
    try {
        AccountingIntegrationService::onReturnToVendorCompleted($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (procurement.rtv_completed): ' . $e->getMessage());
    }
}, 50);

// ── Rentals ─────────────────────────────────────────────────
// When a rental deposit is collected, record deposit liability
EventBus::listen('rental.deposit_collected', function (array $data): void {
    try {
        AccountingIntegrationService::onRentalDepositCollected($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (rental.deposit_collected): ' . $e->getMessage());
    }
}, 50);

// When a rental deposit is refunded, reverse deposit liability
EventBus::listen('rental.deposit_refunded', function (array $data): void {
    try {
        AccountingIntegrationService::onRentalDepositRefunded($data);
    } catch (\Throwable $e) {
        \App\Core\Logger::error('Accounting auto-post failed (rental.deposit_refunded): ' . $e->getMessage());
    }
}, 50);
