<?php
declare(strict_types=1);

namespace App\Modules\Members\Services;

use App\Core\App;
use App\Modules\Rules\Services\RuleEngine;

final class MembershipRulesService
{
    // ══════════════════════════════════════════════════════════════════════
    // Member Type Classification (أنواع الأعضاء)
    // ══════════════════════════════════════════════════════════════════════

    public static function getMemberTypes(): array
    {
        return [
            [
                'code'        => 'working',
                'name_ar'     => 'عضو عامل',
                'name_en'     => 'Working Member',
                'min_age'     => 21,
                'description' => 'العضو الأساسي الذي لا يقل سنه عن 21 عام',
            ],
            [
                'code'        => 'dependent',
                'name_ar'     => 'عضو تابع',
                'name_en'     => 'Dependent Member',
                'min_age'     => 0,
                'description' => 'الأبناء والزوج/الزوجة أقل من 21 سنة',
            ],
            [
                'code'        => 'temporary',
                'name_ar'     => 'عضو مؤقت',
                'name_en'     => 'Temporary Member',
                'min_age'     => 0,
                'description' => 'عضو مضاف بدون حق الفصل أو العضوية المستقلة',
            ],
            [
                'code'        => 'honorary',
                'name_ar'     => 'عضو شرفي',
                'name_en'     => 'Honorary Member',
                'min_age'     => 0,
                'description' => 'عضوية لمدة سنة قابلة للتجديد بدون رسوم',
            ],
            [
                'code'        => 'athletic',
                'name_ar'     => 'عضو رياضي',
                'name_en'     => 'Athletic Member',
                'min_age'     => 0,
                'description' => 'لاعب مسجل بأحد الألعاب لمدة 8 سنوات',
            ],
            [
                'code'        => 'foreign',
                'name_ar'     => 'عضو أجنبي',
                'name_en'     => 'Foreign Member',
                'min_age'     => 21,
                'description' => 'غير حامل الجنسية المصرية — رسوم 10,000 دولار',
            ],
            [
                'code'        => 'seasonal',
                'name_ar'     => 'عضو موسمي',
                'name_en'     => 'Seasonal Member',
                'min_age'     => 0,
                'description' => 'عضوية موسمية مؤقتة',
            ],
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Creatable Membership Types (أنواع العضويات الرئيسية عند الإنشاء)
    // ══════════════════════════════════════════════════════════════════════

    public static function getCreatableMembershipTypes(): array
    {
        return [
            'working'  => ['name_ar' => 'عضو عامل', 'min_age' => 21, 'allows_dependents' => true, 'requires_qualification' => true],
            'seasonal' => ['name_ar' => 'عضو موسمي', 'min_age' => 0, 'allows_dependents' => true, 'requires_qualification' => false],
            'sports'   => ['name_ar' => 'عضو رياضي', 'min_age' => 0, 'allows_dependents' => true, 'requires_qualification' => false],
            'honorary' => ['name_ar' => 'عضو شرفي', 'min_age' => 0, 'allows_dependents' => true, 'requires_qualification' => false],
            'foreign'  => ['name_ar' => 'عضو أجنبي', 'min_age' => 21, 'allows_dependents' => true, 'requires_qualification' => false],
        ];
    }

    public static function allowsDependents(string $membershipType): bool
    {
        $types = self::getCreatableMembershipTypes();
        return $types[$membershipType]['allows_dependents'] ?? false;
    }

    public static function getMinAgeForType(string $membershipType): int
    {
        $types = self::getCreatableMembershipTypes();
        return $types[$membershipType]['min_age'] ?? 0;
    }

    public static function requiresQualification(string $membershipType): bool
    {
        $types = self::getCreatableMembershipTypes();
        return $types[$membershipType]['requires_qualification'] ?? false;
    }

    public static function getMembershipTypeLabel(string $membershipType): string
    {
        $types = self::getCreatableMembershipTypes();
        return $types[$membershipType]['name_ar'] ?? 'عضو عامل';
    }

    public static function classifyMemberType(string $relationship, int $age): string
    {
        if ($relationship === 'self') {
            return $age >= 21 ? 'working' : 'dependent';
        }

        if (in_array($relationship, ['spouse', 'husband', 'wife'])) {
            return $age >= 21 ? 'working' : 'dependent';
        }

        if (in_array($relationship, ['child', 'son', 'daughter'])) {
            return 'dependent';
        }

        return 'temporary';
    }

    public static function validateMinAge(string $memberType, int $age): array
    {
        if ($memberType === 'working' && $age < 21) {
            return ['valid' => false, 'reason' => 'العضو العامل الأساسي لا يقل سنه عن 21 عام'];
        }
        return ['valid' => true];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Form Fees (رسوم الاستمارات)
    // ══════════════════════════════════════════════════════════════════════

    public static function getNewMembershipFormFee(): array
    {
        $override = RuleEngine::get('membership.new_form_fee');
        $formAmount = ($override['form_amount'] ?? '500');
        $martyrsStamp = ($override['martyrs_stamp'] ?? '5');
        $total = bcadd($formAmount, $martyrsStamp, 2);

        return [
            'form_amount'    => $formAmount,
            'martyrs_stamp'  => $martyrsStamp,
            'total'          => $total,
            'description'    => 'استمارة العضوية الجديدة 500 جنيه + 5 طابع شهداء',
        ];
    }

    public static function getAdditionFormFee(): array
    {
        $override = RuleEngine::get('membership.addition_form_fee');
        $formFee = ($override['amount'] ?? '570');
        $annualSub = self::getAnnualRates(self::currentFinancialYear())['member'] ?? '492';
        $devFee = self::getAnnualRates(self::currentFinancialYear())['dev'] ?? '35';
        $totalAnnual = bcadd($annualSub, $devFee, 2);
        $total = bcadd($formFee, $totalAnnual, 2);

        return [
            'form_fee'            => $formFee,
            'annual_subscription' => $totalAnnual,
            'total'               => $total,
            'description'         => 'أي إضافة بعد إنشاء العضوية: 570 جنيه + الاشتراك السنوي',
        ];
    }

    public static function getIncludedInMembership(): array
    {
        return [
            'spouse_count'       => 1,
            'children_under_18'  => 3,
            'description'        => 'تشمل العضوية: زوج + زوجة + 3 أبناء تحت 18 عام',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Membership Pricing
    // ══════════════════════════════════════════════════════════════════════

    public static function getMembershipPrice(string $qualificationLevel, ?string $asOfDate = null): string
    {
        $asOfDate = $asOfDate ?? date('Y-m-d');
        $cutoff = '2024-07-01';

        $override = RuleEngine::get('membership.price.' . $qualificationLevel, null, $asOfDate);
        if ($override !== null) {
            return (string) ($override['amount'] ?? $override['value'] ?? '0');
        }

        if ($asOfDate < $cutoff) {
            return match ($qualificationLevel) {
                'high', 'عالى'     => '114000',
                'medium', 'متوسط' => '171000',
                'none', 'بدون'    => '228000',
                default            => '0',
            };
        }

        return match ($qualificationLevel) {
            'high', 'عالى'     => '150000',
            'medium', 'متوسط' => '225000',
            'none', 'بدون'    => '300000',
            default            => '0',
        };
    }

    // ══════════════════════════════════════════════════════════════════════
    // Children Fees (أبناء العضو العامل)
    // ══════════════════════════════════════════════════════════════════════

    public static function getChildAdditionFee(int $childAge, string $membershipValue): array
    {
        $override = RuleEngine::get('membership.child_fee.' . $childAge);
        if ($override !== null && isset($override['percentage'])) {
            $pct = (string) $override['percentage'];
            return [
                'percentage' => $pct,
                'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
                'type'       => $override['type'] ?? 'regular',
            ];
        }

        if ($childAge < 18) {
            // 4th child under 18
            $pct = '5';
            return [
                'percentage' => $pct,
                'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
                'type'       => 'regular',
            ];
        }

        if ($childAge === 18) {
            $pct = '10';
        } elseif ($childAge === 19) {
            $pct = '15';
        } elseif ($childAge === 20) {
            $pct = '20';
        } else {
            // 21+: temporary until 25
            $pct = '15';
            return [
                'percentage' => $pct,
                'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
                'type'       => 'temporary',
            ];
        }

        return [
            'percentage' => $pct,
            'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
            'type'       => 'regular',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Acquired Member Children (أبناء العضو مكتسب العضوية بعد الانفصال)
    // ══════════════════════════════════════════════════════════════════════

    public static function getAcquiredMemberChildFee(int $childAge, string $membershipValue): array
    {
        $override = RuleEngine::get('membership.acquired_child_fee.' . $childAge);
        if ($override !== null && isset($override['percentage'])) {
            $pct = (string) $override['percentage'];
            return [
                'percentage' => $pct,
                'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
            ];
        }

        if ($childAge < 12) {
            $pct = '15';
        } elseif ($childAge < 16) {
            $pct = '20';
        } elseif ($childAge < 18) {
            $pct = '25';
        } else {
            $pct = '30';
        }

        return [
            'percentage' => $pct,
            'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Spouse Fees (زوجات العضو العامل)
    // ══════════════════════════════════════════════════════════════════════

    public static function getSpouseAdditionFee(
        int $spouseOrder,
        string $membershipValue,
        ?string $marriageOrMembershipDate = null,
        bool $isForeign = false
    ): array {
        $override = RuleEngine::get('membership.spouse_fee.' . $spouseOrder);
        if ($override !== null && isset($override['percentage'])) {
            return $override;
        }

        if ($spouseOrder === 1 && !$isForeign) {
            return [
                'percentage'  => '0',
                'amount'      => '0.00',
                'annual_fee'  => '0.00',
                'years'       => 0,
                'total'       => '0.00',
            ];
        }

        if ($isForeign && $spouseOrder === 1) {
            $pct = '15';
            $amount = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);
            return [
                'percentage'  => $pct,
                'amount'      => $amount,
                'annual_fee'  => '0.00',
                'years'       => 0,
                'total'       => $amount,
            ];
        }

        $config = match ($spouseOrder) {
            2 => ['percentage' => '10', 'annual_fee' => '150'],
            3 => ['percentage' => '20', 'annual_fee' => '200'],
            default => ['percentage' => '30', 'annual_fee' => '300'],
        };

        $baseAmount = bcdiv(bcmul($membershipValue, $config['percentage'], 4), '100', 2);

        $years = 0;
        $annualTotal = '0.00';
        if ($marriageOrMembershipDate !== null) {
            $start = new \DateTime($marriageOrMembershipDate);
            $now = new \DateTime();
            $diff = $start->diff($now);
            $years = $diff->y;
            if ($diff->m > 0 || $diff->d > 0) {
                $years++;
            }
            $annualTotal = bcmul((string) $years, $config['annual_fee'], 2);
        }

        $total = bcadd($baseAmount, $annualTotal, 2);

        return [
            'percentage'  => $config['percentage'],
            'amount'      => $baseAmount,
            'annual_fee'  => $config['annual_fee'],
            'years'       => $years,
            'total'       => $total,
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Acquired Member Spouse Fee
    // ══════════════════════════════════════════════════════════════════════

    public static function getAcquiredMemberSpouseFee(int $spouseOrder, string $membershipValue): array
    {
        $override = RuleEngine::get('membership.acquired_spouse_fee.' . $spouseOrder);
        if ($override !== null && isset($override['percentage'])) {
            $pct = (string) $override['percentage'];
            return [
                'percentage' => $pct,
                'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
            ];
        }

        $pct = match ($spouseOrder) {
            1       => '50',
            default => '75',
        };

        return [
            'percentage' => $pct,
            'amount'     => bcdiv(bcmul($membershipValue, $pct, 4), '100', 2),
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Separation/Transfer Fees (رسوم الفصل)
    // ══════════════════════════════════════════════════════════════════════

    public static function getSeparationFee(int $yearsSinceAddition, string $currentMembershipValue): array
    {
        $override = RuleEngine::get('membership.separation_fee');
        $formFee = '570';

        if ($override !== null && isset($override['tiers'])) {
            $tiers = $override['tiers'];
        } else {
            $tiers = [
                1 => '30',
                2 => '20',
                3 => '15',
                4 => '10',
                5 => '5',
            ];
        }

        if (isset($tiers[$yearsSinceAddition])) {
            $pct = (string) $tiers[$yearsSinceAddition];
        } elseif ($yearsSinceAddition >= 6) {
            $pct = '2.5';
        } else {
            $pct = '30';
        }

        $separationAmount = bcdiv(bcmul($currentMembershipValue, $pct, 4), '100', 2);
        $annualSubscription = self::getAnnualRates(self::currentFinancialYear())['member'] ?? '410';

        return [
            'percentage'          => $pct,
            'separation_amount'   => $separationAmount,
            'form_fee'            => $formFee,
            'annual_subscription' => $annualSubscription,
            'total'               => bcadd(bcadd($separationAmount, $formFee, 2), $annualSubscription, 2),
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Transfer Eligibility
    // ══════════════════════════════════════════════════════════════════════

    public static function canChildSeparate(string $gender, int $age, ?bool $isEmployed = null, ?bool $isMarried = null): array
    {
        if ($gender === 'female') {
            if ($isMarried === true) {
                return ['eligible' => true, 'reason' => 'ابنة متزوجة — يحق لها الفصل'];
            }
            return ['eligible' => false, 'reason' => 'الابنة غير متزوجة — لا يحق لها الفصل'];
        }

        // Male
        if ($age >= 25) {
            return ['eligible' => true, 'reason' => 'ابن بلغ 25 سنة — يحق له الفصل'];
        }

        if ($isEmployed === true) {
            return ['eligible' => true, 'reason' => 'ابن متخرج وموظف — يحق له الفصل'];
        }

        return ['eligible' => false, 'reason' => 'ابن لم يبلغ 25 سنة وغير موظف — لا يحق له الفصل'];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Divorce Transfer Rules
    // ══════════════════════════════════════════════════════════════════════

    public static function getDivorceTransferFee(
        string $divorceScenario,
        string $membershipValue,
        ?int $yearsSinceMembership = null
    ): array {
        $annualSubscription = self::getAnnualRates(self::currentFinancialYear())['member'] ?? '410';

        switch ($divorceScenario) {
            case 'both_working_before_marriage':
                return [
                    'type'                => 'annual_subscription_only',
                    'amount'              => $annualSubscription,
                    'membership_basis'    => 'working_member',
                    'conditions'          => self::getDivorceConditions($yearsSinceMembership),
                ];

            case 'same_form':
                $pct = '10';
                $amount = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);
                return [
                    'type'                => 'percentage',
                    'percentage'          => $pct,
                    'amount'              => $amount,
                    'membership_basis'    => 'working_member',
                    'conditions'          => self::getDivorceConditions($yearsSinceMembership),
                ];

            case 'joined_after':
                $pct = '50';
                $amount = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);
                return [
                    'type'                => 'percentage',
                    'percentage'          => $pct,
                    'amount'              => $amount,
                    'membership_basis'    => 'acquired_member',
                    'conditions'          => self::getDivorceConditions($yearsSinceMembership),
                ];

            default:
                return [
                    'type'       => 'unknown',
                    'amount'     => '0.00',
                    'conditions' => [],
                ];
        }
    }

    private static function getDivorceConditions(?int $yearsSinceMembership): array
    {
        $conditions = [];
        $conditions[] = [
            'rule'        => 'divorce_within_one_year',
            'description' => 'يجب أن يكون الطلاق قد تم خلال عام واحد',
        ];
        $conditions[] = [
            'rule'        => 'membership_min_5_years',
            'description' => 'مضى على العضوية 5 سنوات على الأقل (يُعفى إذا وُجد أبناء)',
            'met'         => $yearsSinceMembership !== null ? $yearsSinceMembership >= 5 : null,
            'waivable'    => true,
            'waiver_reason' => 'وجود أبناء',
        ];
        return $conditions;
    }

    // ══════════════════════════════════════════════════════════════════════
    // Freeze Rules
    // ══════════════════════════════════════════════════════════════════════

    public static function shouldFreezeMaleChild(int $age): bool
    {
        return $age >= 25;
    }

    public static function isFreezeActive(array $child): bool
    {
        if (($child['gender'] ?? '') !== 'male') {
            return false;
        }
        $age = (int) ($child['age_years'] ?? 0);
        if ($age < 25) {
            return false;
        }
        $status = $child['status'] ?? $child['membership_status'] ?? '';
        return in_array($status, ['frozen', 'مجمد'], true);
    }

    // ══════════════════════════════════════════════════════════════════════
    // Death Transfer
    // ══════════════════════════════════════════════════════════════════════

    public static function getDeathTransferRules(): array
    {
        $annualSubscription = self::getAnnualRates(self::currentFinancialYear())['member'] ?? '410';
        return [
            'beneficiary'         => 'spouse',
            'retains_number'      => true,
            'form_fee'            => '570',
            'annual_subscription' => $annualSubscription,
            'membership_fee'      => '0.00',
            'description'         => 'تنتقل العضوية للزوج/الزوجة بنفس الرقم مع سداد رسوم الاستمارة والاشتراك السنوي فقط',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Waiver (التنازل)
    // ══════════════════════════════════════════════════════════════════════

    public static function getWaiverFee(string $membershipValue): array
    {
        $override = RuleEngine::get('membership.waiver_fee');
        $pct = ($override !== null && isset($override['percentage']))
            ? (string) $override['percentage']
            : '30';

        $amount = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);

        return [
            'percentage' => $pct,
            'amount'     => $amount,
        ];
    }

    public static function getWaiverConditions(): array
    {
        return [
            [
                'code'        => 'board_approval',
                'description' => 'موافقة مجلس الأمناء',
                'required'    => true,
            ],
            [
                'code'        => 'dependants_limit',
                'description' => 'لا يزيد عدد الأعضاء للعضو المتنازل له عن عدد الأعضاء التابعين للعضو المتنازل',
                'required'    => true,
            ],
            [
                'code'        => 'extra_dependants_fee',
                'description' => 'في حالة رغبة المتنازل له في إضافة أعضاء بالزيادة يلتزم بسداد الرسوم المحددة من مجلس الأمناء',
                'required'    => false,
            ],
            [
                'code'        => 'annual_subscription_paid',
                'description' => 'التجديد السنوي قبل إتمام التنازل',
                'required'    => true,
            ],
            [
                'code'        => 'new_form_required',
                'description' => 'استمارة عضوية جديدة للعضو المتنازل له',
                'required'    => true,
            ],
            [
                'code'        => 'same_membership_number',
                'description' => 'يصبح العضو الأساسي بنفس رقم العضوية المتنازل',
                'required'    => true,
            ],
            [
                'code'        => 'archive_old_data',
                'description' => 'يتم نقل جميع البيانات القديمة إلى الأرشيف للحفظ',
                'required'    => true,
            ],
        ];
    }

    public static function getWaiverProcess(): array
    {
        return [
            'fee_percentage'      => '30',
            'retains_number'      => true,
            'requires_new_form'   => true,
            'archive_source_data' => true,
            'steps'               => [
                'طلب تنازل مع موافقة مجلس الأمناء',
                'سداد 30% من قيمة العضوية وقت التنازل',
                'استمارة عضوية جديدة للمتنازل له',
                'سداد التجديد السنوي',
                'أرشفة بيانات العضو المتنازل',
                'تسجيل المتنازل له بنفس رقم العضوية',
            ],
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Temporary Members (العضو المؤقت)
    // ══════════════════════════════════════════════════════════════════════

    public static function getTemporaryMemberFee(string $membershipValue): string
    {
        $override = RuleEngine::get('membership.temporary_fee');
        $pct = ($override !== null && isset($override['percentage']))
            ? (string) $override['percentage']
            : '10';

        return bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);
    }

    public static function getTemporaryMemberCategories(): array
    {
        return [
            [
                'code'             => 'special_needs_over_21',
                'name_ar'          => 'أبناء ذوي الاحتياجات الخاصة فوق 21 سنة',
                'fee_applies'      => true,
                'can_separate'     => false,
            ],
            [
                'code'             => 'parents',
                'name_ar'          => 'والدا العضو العامل الأصلي',
                'fee_applies'      => true,
                'can_separate'     => false,
            ],
            [
                'code'             => 'unmarried_unemployed_daughters',
                'name_ar'          => 'بنات العضو الغير متزوجات واللاتي لا يعملن بأجر',
                'fee_applies'      => true,
                'can_separate'     => false,
            ],
            [
                'code'             => 'sisters_under_25',
                'name_ar'          => 'شقيقات العضو أقل من 25 سنة (غير متزوجات/مطلقات/أرامل، غير عاملات، مقيمات معه، وهو عائلهن الوحيد)',
                'fee_applies'      => true,
                'can_separate'     => false,
                'max_age'          => 25,
            ],
            [
                'code'             => 'stepchildren_under_25',
                'name_ar'          => 'أبناء الزوج/الزوجة من غير أبناء العضو العامل (أقل من 25 سنة)',
                'fee_applies'      => true,
                'can_separate'     => false,
                'max_age'          => 25,
            ],
            [
                'code'             => 'orphan_sponsored',
                'name_ar'          => 'الطفل اليتيم الذي تكفله أسرة العضو (قانون 12/1996) حتى 25 عام',
                'fee_applies'      => true,
                'fee_amount'       => 'غير محدد حالياً',
                'can_separate'     => false,
                'max_age'          => 25,
            ],
            [
                'code'             => 'disabled_sibling',
                'name_ar'          => 'شقيق العضو المعاق (بشرط أن يكون العضو عائله الوحيد)',
                'fee_applies'      => true,
                'fee_amount'       => 'غير محدد حالياً',
                'can_separate'     => false,
            ],
            [
                'code'             => 'nanny',
                'name_ar'          => 'المربية',
                'fee_percentage'   => '5',
                'fee_applies'      => true,
                'can_separate'     => false,
            ],
            [
                'code'             => 'championship_exempt',
                'name_ar'          => 'حاصل على بطولات جمهورية (بدون رسوم إضافة)',
                'fee_applies'      => false,
                'can_separate'     => false,
            ],
        ];
    }

    public static function getCompanionFee(string $categoryCode, string $membershipValue): array
    {
        $categories = self::getTemporaryMemberCategories();
        $category = null;
        foreach ($categories as $cat) {
            if ($cat['code'] === $categoryCode) {
                $category = $cat;
                break;
            }
        }

        if (!$category) {
            return ['error' => 'فئة غير معروفة', 'fee' => '0.00'];
        }

        if (!$category['fee_applies']) {
            return ['fee' => '0.00', 'category' => $category['name_ar'], 'exempt' => true];
        }

        if (isset($category['fee_percentage'])) {
            $pct = $category['fee_percentage'];
            $fee = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);
            return ['fee' => $fee, 'percentage' => $pct, 'category' => $category['name_ar']];
        }

        // Default: 10% for temporary members
        $pct = '10';
        $fee = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);
        return ['fee' => $fee, 'percentage' => $pct, 'category' => $category['name_ar']];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Honorary Member (العضو الشرفي)
    // ══════════════════════════════════════════════════════════════════════

    public static function getHonoraryMemberRules(): array
    {
        return [
            'duration_years'         => 1,
            'renewable'              => true,
            'fees'                   => '0.00',
            'annual_subscription'    => '0.00',
            'requires_board_approval'=> true,
            'conditions'             => [
                'قرار من مجلس الأمناء',
                'نظير خدمات جليلة للدولة أو المنشأة الرياضية',
            ],
            'description'            => 'عضوية لمدة سنة واحدة قابلة للتجديد بدون رسوم أو اشتراكات',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Athletic Member (العضو الرياضي)
    // ══════════════════════════════════════════════════════════════════════

    public static function getAthleticMemberConversionRules(): array
    {
        $override = RuleEngine::get('membership.athletic_conversion');

        return [
            'conversion_percentage'  => ($override['percentage'] ?? '50'),
            'min_playing_years'      => ($override['min_years'] ?? 8),
            'conditions'             => [
                'مرور 8 سنوات على الأقل لاعباً بأحد الألعاب بالمدينة الرياضية',
                'مسجل باتحاد اللعبة باسم المدينة الرياضية',
                'تمثيل المدينة الرياضية في أعلى مستوى تنافسي طوال المدة',
            ],
            'description'            => 'رسوم تحويل 50% من قيمة العضوية الجديدة وقت تقديم الطلب',
        ];
    }

    public static function getAthleticConversionFee(string $membershipValue): array
    {
        $rules = self::getAthleticMemberConversionRules();
        $pct = $rules['conversion_percentage'];
        $fee = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);

        return [
            'percentage' => $pct,
            'fee'        => $fee,
            'conditions' => $rules['conditions'],
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Foreign Member (العضو الأجنبي)
    // ══════════════════════════════════════════════════════════════════════

    public static function getForeignMemberRules(): array
    {
        $override = RuleEngine::get('membership.foreign_member');

        return [
            'fee_usd'           => ($override['fee_usd'] ?? '10000'),
            'currency'          => 'USD',
            'includes'          => 'زوج + زوجة + 3 أبناء',
            'has_full_rights'   => true,
            'can_separate'      => true,
            'can_transfer'      => true,
            'description'       => 'الذي لا يحمل الجنسية المصرية — رسوم 10,000 دولار شاملة العائلة',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Annual Subscription Rates
    // ══════════════════════════════════════════════════════════════════════

    public static function getAnnualRates(string $financialYear): array
    {
        $override = RuleEngine::get('membership.annual_rates.' . $financialYear);
        if ($override !== null) {
            return $override;
        }

        return match ($financialYear) {
            '2023/2024' => [
                'member' => '410',
                'spouse' => '410',
                'child'  => '185',
                'temp'   => '185',
                'dev'    => '35',
                'note'   => 'خصم 50% مطبق',
            ],
            '2024/2025' => [
                'member' => '410',
                'spouse' => '410',
                'child'  => '185',
                'temp'   => '185',
                'dev'    => '35',
            ],
            '2025/2026' => [
                'member' => '492',
                'spouse' => '492',
                'child'  => '222',
                'temp'   => '222',
                'dev'    => '35',
                'note'   => 'زيادة 20%',
            ],
            default => [
                'member' => '492',
                'spouse' => '492',
                'child'  => '222',
                'temp'   => '222',
                'dev'    => '35',
            ],
        };
    }

    // ══════════════════════════════════════════════════════════════════════
    // Installment Rules
    // ══════════════════════════════════════════════════════════════════════

    public static function getInstallmentTerms(string $membershipValue, string $downPayment): array
    {
        $override = RuleEngine::get('membership.installment_terms') ?? [];

        $minDownPct = !empty($override['min_down_percentage']) ? (string) $override['min_down_percentage'] : '25';
        $maxMonths = !empty($override['max_months']) ? (int) $override['max_months'] : 30;
        $annualInterest = !empty($override['annual_interest']) ? (string) $override['annual_interest'] : '22';
        $cashGraceDays = !empty($override['cash_grace_days']) ? (int) $override['cash_grace_days'] : 30;

        $minDownAmount = bcdiv(bcmul($membershipValue, $minDownPct, 4), '100', 2);
        $downPaymentValid = bccomp($downPayment, $minDownAmount, 2) >= 0;

        $remaining = bcsub($membershipValue, $downPayment, 2);
        if (bccomp($remaining, '0', 2) < 0) {
            $remaining = '0.00';
        }

        $monthlyInterestRate = bcdiv($annualInterest, '1200', 8);
        $totalInterest = bcdiv(bcmul(bcmul($remaining, $annualInterest, 4), (string) $maxMonths, 4), '1200', 2);
        $totalWithInterest = bcadd($remaining, $totalInterest, 2);
        $monthlyInstallment = $maxMonths > 0
            ? bcdiv($totalWithInterest, (string) $maxMonths, 2)
            : '0.00';

        return [
            'membership_value'      => $membershipValue,
            'min_down_percentage'   => $minDownPct,
            'min_down_amount'       => $minDownAmount,
            'down_payment'          => $downPayment,
            'down_payment_valid'    => $downPaymentValid,
            'remaining'             => $remaining,
            'max_months'            => $maxMonths,
            'annual_interest'       => $annualInterest,
            'monthly_interest_rate' => $monthlyInterestRate,
            'total_interest'        => $totalInterest,
            'total_with_interest'   => $totalWithInterest,
            'monthly_installment'   => $monthlyInstallment,
            'cash_grace_days'       => $cashGraceDays,
            'cash_note'             => 'السداد الكامل خلال ' . $cashGraceDays . ' يوم بدون فوائد',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Penalties & Violations (مخالفات الأعضاء ومساءلتهم)
    // ══════════════════════════════════════════════════════════════════════

    public static function getViolationPenalties(): array
    {
        return [
            ['code' => 'attention',  'name_ar' => 'لفت نظر',         'severity' => 1, 'financial' => false],
            ['code' => 'warning',    'name_ar' => 'إنذار',            'severity' => 2, 'financial' => false],
            ['code' => 'fine',       'name_ar' => 'غرامة',            'severity' => 3, 'financial' => true, 'min' => '1000', 'max' => '10000'],
            ['code' => 'suspension', 'name_ar' => 'إيقاف عن مزاولة النشاط', 'severity' => 4, 'financial' => false, 'max_duration_months' => 6],
            ['code' => 'ban',        'name_ar' => 'حرمان من دخول النادي', 'severity' => 5, 'financial' => false, 'max_duration_months' => 6],
            ['code' => 'expulsion',  'name_ar' => 'فصل العضو',       'severity' => 6, 'financial' => false, 'no_refund' => true],
        ];
    }

    public static function validateFineAmount(string $amount): array
    {
        $min = '1000';
        $max = '10000';
        $override = RuleEngine::get('membership.fine_limits');
        if ($override) {
            $min = (string) ($override['min'] ?? '1000');
            $max = (string) ($override['max'] ?? '10000');
        }

        if (bccomp($amount, $min, 2) < 0) {
            return ['valid' => false, 'reason' => 'الغرامة لا تقل عن ' . $min . ' جنيه'];
        }
        if (bccomp($amount, $max, 2) > 0) {
            return ['valid' => false, 'reason' => 'الغرامة لا تزيد عن ' . $max . ' جنيه'];
        }
        return ['valid' => true];
    }

    public static function canAppeal(string $penaltyDate): bool
    {
        $deadline = (new \DateTime($penaltyDate))->modify('+15 days');
        return new \DateTime() <= $deadline;
    }

    public static function getAppealDeadline(string $penaltyDate): string
    {
        return (new \DateTime($penaltyDate))->modify('+15 days')->format('Y-m-d');
    }

    public static function canRequestReview(string $expulsionDate): bool
    {
        $eligibleDate = (new \DateTime($expulsionDate))->modify('+6 months');
        return new \DateTime() >= $eligibleDate;
    }

    public static function getReviewEligibleDate(string $expulsionDate): string
    {
        return (new \DateTime($expulsionDate))->modify('+6 months')->format('Y-m-d');
    }

    // ══════════════════════════════════════════════════════════════════════
    // Fines & Penalties Accumulation (الغرامات)
    // ══════════════════════════════════════════════════════════════════════

    public static function getFineAccumulationRules(): array
    {
        return [
            'max_accumulation_years' => 5,
            'drop_after_max'         => true,
            'description'            => 'تطبق غرامات وتستمر في التراكم لمدة 5 سنوات كحد أقصى — بعدها إسقاط العضوية',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Membership Termination & Drop (انتهاء وإسقاط العضوية)
    // ══════════════════════════════════════════════════════════════════════

    public static function getMembershipEndReasons(): array
    {
        return [
            ['code' => 'death',          'name_ar' => 'الوفاة',                            'type' => 'termination'],
            ['code' => 'waiver',         'name_ar' => 'التنازل عن العضوية',                'type' => 'termination'],
            ['code' => 'board_decision', 'name_ar' => 'إنهاء العضوية بقرار مجلس أمناء',   'type' => 'termination'],
            ['code' => 'condition_lost', 'name_ar' => 'فقد شرط من شروط العضوية',           'type' => 'drop'],
            ['code' => 'expulsion',      'name_ar' => 'الفصل من العضوية طبقاً للائحة',     'type' => 'drop'],
            ['code' => 'installment_default', 'name_ar' => 'عدم الالتزام بسداد الأقساط المستحقة', 'type' => 'drop'],
            ['code' => 'unpaid_5_years', 'name_ar' => 'تأخر عن سداد الاشتراك السنوي 5 سنوات متتالية', 'type' => 'drop'],
        ];
    }

    public static function shouldDropMembership(int $unpaidYears, bool $hasUnpaidInstallments = false): bool
    {
        if ($hasUnpaidInstallments) {
            return true;
        }
        return $unpaidYears >= 5;
    }

    public static function canReinstate(string $dropDate): array
    {
        $deadline = (new \DateTime($dropDate))->modify('+1 year');
        $eligible = new \DateTime() <= $deadline;

        return [
            'eligible'        => $eligible,
            'deadline'        => $deadline->format('Y-m-d'),
            'requires'        => [
                'سداد جميع المبالغ المتأخرة',
                'ما يحدده مجلس الأمناء من غرامات',
            ],
            'board_approval'  => true,
            'description'     => $eligible
                ? 'يجوز إعادة العضوية خلال سنة من تاريخ الإسقاط بعد السداد وموافقة المجلس'
                : 'انتهت مهلة السنة — لا يمكن إعادة العضوية',
        ];
    }

    public static function getBlockNonPayingMemberRules(): array
    {
        return [
            'block_entry'        => true,
            'block_carnet'       => true,
            'block_subscription' => true,
            'description'        => 'منع دخول الأعضاء الغير مسددين ومنع طباعة الكارنيه',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Group Discounts (المجمعة)
    // ══════════════════════════════════════════════════════════════════════

    public static function getGroupDiscount(int $membershipCount): array
    {
        $override = RuleEngine::get('membership.group_discount');
        if ($override !== null && isset($override['tiers'])) {
            $tiers = $override['tiers'];
        } else {
            $tiers = [
                ['min' => 5,  'max' => 10, 'percentage' => '3'],
                ['min' => 11, 'max' => 20, 'percentage' => '7'],
                ['min' => 21, 'max' => null, 'percentage' => '10'],
            ];
        }

        foreach ($tiers as $tier) {
            $min = (int) $tier['min'];
            $max = $tier['max'] !== null ? (int) $tier['max'] : PHP_INT_MAX;
            if ($membershipCount >= $min && $membershipCount <= $max) {
                return [
                    'eligible'   => true,
                    'percentage' => $tier['percentage'],
                    'count'      => $membershipCount,
                ];
            }
        }

        return [
            'eligible'   => false,
            'percentage' => '0',
            'count'      => $membershipCount,
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Carnet Rules (طباعة الكارنيهات)
    // ══════════════════════════════════════════════════════════════════════

    public static function canPrintCarnet(int $memberId): array
    {
        $db = App::getInstance()->db();

        $currentYear = self::currentFinancialYear();

        // Check member status
        $member = $db->selectOne(
            "SELECT status FROM members WHERE id = ? AND is_archived = 0",
            [$memberId]
        );

        if (!$member) {
            return ['allowed' => false, 'reason' => 'العضو غير موجود'];
        }

        if (in_array($member['status'], ['suspended', 'frozen', 'dropped'])) {
            return ['allowed' => false, 'reason' => 'العضوية غير فعالة (حالة: ' . $member['status'] . ')'];
        }

        // Check annual subscription paid
        $paid = $db->selectOne(
            "SELECT id FROM payments WHERE member_id = ? AND payment_type = 'annual_subscription' AND financial_year = ? AND is_voided = 0 LIMIT 1",
            [$memberId, $currentYear]
        );

        if (!$paid) {
            return ['allowed' => false, 'reason' => 'لم يتم سداد الاشتراك السنوي للعام ' . $currentYear];
        }

        // Check outstanding installments
        $unpaidInstallments = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM installment_schedule s
             JOIN installment_plans p ON p.id = s.installment_plan_id
             WHERE p.member_id = ? AND p.status = 'active' AND s.status IN ('pending','overdue') AND s.due_date < CURDATE()",
            [$memberId]
        );
        if ((int) ($unpaidInstallments['cnt'] ?? 0) > 0) {
            return ['allowed' => false, 'reason' => 'يوجد أقساط مستحقة غير مسددة'];
        }

        // Check unpaid fines
        $unpaidFines = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM fines WHERE member_id = ? AND penalty_type = 'fine' AND status = 'imposed' AND (amount - paid_amount) > 0",
            [$memberId]
        );
        if ((int) ($unpaidFines['cnt'] ?? 0) > 0) {
            return ['allowed' => false, 'reason' => 'يوجد غرامات غير مسددة'];
        }

        return ['allowed' => true, 'reason' => 'مسموح بالطباعة'];
    }

    public static function getLostCarnetFee(): array
    {
        $override = RuleEngine::get('membership.lost_carnet_fee');
        return [
            'fee'         => ($override['amount'] ?? '200'),
            'description' => 'رسوم بدل فاقد كارنيه',
        ];
    }

    public static function getCarnetPrintRules(): array
    {
        return [
            'requires_annual_paid'     => true,
            'requires_no_installment_debt' => true,
            'requires_active_status'   => true,
            'log_employee_and_date'    => true,
            'description'              => 'لا يُسمح بطباعة الكارنيهات إلا بعد سداد الاشتراك السنوي — يظهر اسم الموظف والتاريخ',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Numbering (نظام ترقيم العضويات)
    // ══════════════════════════════════════════════════════════════════════

    public static function getNewNumberingFormat(): array
    {
        $override = RuleEngine::get('NEW_NUMBERING_START_DATE');

        return [
            'format'           => '2/XXXX',
            'start_from'       => ($override['start_number'] ?? '1001'),
            'prefix'           => ($override['prefix'] ?? '2'),
            'effective_date'   => ($override['effective_date'] ?? '2026-07-01'),
            'applies_to'       => 'new_memberships_only',
            'description'      => 'نظام ترقيم جديد متسلسل يبدأ من 2/1001 — يطبق على العضويات الجديدة فقط حتى 1/7/2026 ثم يعمم',
        ];
    }

    public static function generateNextMembershipNumber(): string
    {
        $db = App::getInstance()->db();
        $config = self::getNewNumberingFormat();
        $prefix = $config['prefix'];

        $last = $db->selectOne(
            "SELECT membership_number FROM members WHERE membership_number LIKE ? ORDER BY id DESC LIMIT 1",
            [$prefix . '/%']
        );

        if ($last) {
            $parts = explode('/', $last['membership_number']);
            $nextNum = (int) ($parts[1] ?? 1000) + 1;
        } else {
            $nextNum = (int) $config['start_from'];
        }

        return $prefix . '/' . $nextNum;
    }

    // ══════════════════════════════════════════════════════════════════════
    // Transfer/Separation Archive Rules (الأرشيف)
    // ══════════════════════════════════════════════════════════════════════

    public static function getArchiveRules(): array
    {
        return [
            'never_delete'                => true,
            'archive_on_transfer'         => true,
            'archive_on_waiver'           => true,
            'archive_on_death_transfer'   => true,
            'archive_on_separation'       => true,
            'track_old_membership_number' => true,
            'track_new_membership_number' => true,
            'log_employee'                => true,
            'log_action_type'             => true,
            'log_timestamp'               => true,
            'log_notes'                   => true,
            'description'                 => 'أي حذف أو تحويل أو تعديل لا يُحذف نهائياً — يتم نقل البيانات القديمة إلى الأرشيف مع الاحتفاظ بالتسلسل',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Board Authority (سلطة مجلس الأمناء)
    // ══════════════════════════════════════════════════════════════════════

    public static function getBoardAuthorityRules(): array
    {
        return [
            'can_adjust_subscription'     => true,
            'can_exempt_from_subscription' => true,
            'can_adjust_membership_price' => true,
            'can_offer_discounts'         => true,
            'can_set_installment_terms'   => true,
            'can_reinstate_dropped'       => true,
            'can_reduce_fine_on_review'   => true,
            'max_fine_on_reinstate'       => '10000',
            'reference_article'           => 'المادة 114',
        ];
    }

    // ══════════════════════════════════════════════════════════════════════
    // Helpers
    // ══════════════════════════════════════════════════════════════════════

    private static function currentFinancialYear(): string
    {
        $month = (int) date('n');
        $year = (int) date('Y');

        if ($month >= 7) {
            return $year . '/' . ($year + 1);
        }
        return ($year - 1) . '/' . $year;
    }
}
