<?php
declare(strict_types=1);

namespace App\Modules\Seasonal\Services;

use App\Modules\Rules\Services\RuleEngine;

/**
 * Pricing engine for seasonal memberships per club regulations.
 *
 * Egyptian members: 6-month or 12-month, fees in EGP, includes pool access.
 * Foreign members: 3/6/12-month, fees in USD, includes pool access, requires residence permit.
 *
 * Family discounts (only ONE per period):
 *   - Parent + child <15 in same period: 500 EGP off total
 *   - Husband + wife in same period: 1000 EGP off total
 *   - Family of 5 (couple + 3 children): 1000 EGP off total
 *
 * No-qualification discount: 10% of seasonal subscription total.
 * Qualified-member discount: 20% of seasonal subscription total.
 * VAT applied on subscription amounts.
 */
final class SeasonalPricingService
{
    // ═══════════════════════════════════════════════════════════════
    // EGYPTIAN PRICING (EGP) — includes swimming pool
    // ═══════════════════════════════════════════════════════════════
    private const EGYPTIAN_PRICES = [
        6 => [
            'member'    => '5500.00',
            'spouse'    => '5500.00',
            'under_15'  => '3500.00',
            '15_to_21'  => '4500.00',
            'over_21'   => '6500.00',
            'over_60'   => '3500.00',
        ],
        12 => [
            'member'    => '10500.00',
            'spouse'    => '10500.00',
            'under_15'  => '5000.00',
            '15_to_21'  => '8500.00',
            'over_21'   => '10500.00',
            'over_60'   => '5000.00',
        ],
    ];

    // ═══════════════════════════════════════════════════════════════
    // FOREIGN PRICING (USD) — includes swimming pool
    // ═══════════════════════════════════════════════════════════════
    private const FOREIGN_PRICES = [
        3 => [
            'member'   => '100.00',
            'spouse'   => '90.00',
            'under_15' => '55.00',
            '15_to_21' => '65.00',
            'over_21'  => '80.00',
        ],
        6 => [
            'member'   => '180.00',
            'spouse'   => '170.00',
            'under_15' => '100.00',
            '15_to_21' => '120.00',
            'over_21'  => '150.00',
        ],
        12 => [
            'member'   => '300.00',
            'spouse'   => '270.00',
            'under_15' => '165.00',
            '15_to_21' => '195.00',
            'over_21'  => '240.00',
        ],
    ];

    private const FAMILY_DISCOUNT_PARENT_CHILD = '500.00';
    private const FAMILY_DISCOUNT_COUPLE = '1000.00';
    private const FAMILY_DISCOUNT_FAMILY_5 = '1000.00';

    private const NO_QUALIFICATION_DISCOUNT_PCT = '10';
    private const QUALIFIED_MEMBER_DISCOUNT_PCT = '20';

    public static function getValidDurations(string $nationalityType): array
    {
        if ($nationalityType === 'foreign') {
            return [3, 6, 12];
        }
        return [6, 12];
    }

    public static function getAgeCategory(int $age): string
    {
        if ($age >= 60) return 'over_60';
        if ($age > 21) return 'over_21';
        if ($age >= 15) return '15_to_21';
        return 'under_15';
    }

    public static function getBasePrice(string $nationalityType, int $durationMonths, string $personType, ?string $ageCategory = null): string
    {
        $override = RuleEngine::get("SEASONAL_PRICE_{$nationalityType}_{$durationMonths}_{$personType}" . ($ageCategory ? "_{$ageCategory}" : ''));
        if ($override && isset($override['amount'])) {
            return $override['amount'];
        }

        if ($nationalityType === 'foreign') {
            $table = self::FOREIGN_PRICES[$durationMonths] ?? [];
        } else {
            $table = self::EGYPTIAN_PRICES[$durationMonths] ?? [];
        }

        if ($personType === 'member') {
            if ($ageCategory === 'over_60' && isset($table['over_60'])) {
                return $table['over_60'];
            }
            return $table['member'] ?? '0.00';
        }

        if ($personType === 'spouse') {
            return $table['spouse'] ?? '0.00';
        }

        return $table[$ageCategory ?? 'under_15'] ?? '0.00';
    }

    public static function getVatRate(): string
    {
        $vatData = RuleEngine::get('SEASONAL_VAT_RATE');
        return $vatData['percentage'] ?? '14.00';
    }

    public static function calculateVat(string $amount): string
    {
        $rate = self::getVatRate();
        return bcdiv(bcmul($amount, $rate, 4), '100', 2);
    }

    public static function calculateFamilyDiscount(array $familyItems): array
    {
        $hasMember = false;
        $hasSpouse = false;
        $childrenUnder15 = 0;
        $totalChildren = 0;

        foreach ($familyItems as $item) {
            if ($item['person_type'] === 'member') $hasMember = true;
            if ($item['person_type'] === 'spouse') $hasSpouse = true;
            if ($item['person_type'] === 'child') {
                $totalChildren++;
                if (($item['age_category'] ?? '') === 'under_15') $childrenUnder15++;
            }
        }

        $totalPeople = count($familyItems);

        // Family of 5+ (couple + 3 children) = 1000 off
        if ($hasMember && $hasSpouse && $totalChildren >= 3 && $totalPeople >= 5) {
            return [
                'amount' => self::FAMILY_DISCOUNT_FAMILY_5,
                'type'   => 'family_5',
                'label'  => 'خصم أسرة مكونة من 5 أفراد (زوج + زوجة + 3 أبناء)',
            ];
        }

        // Husband + wife in same period = 1000 off
        if ($hasMember && $hasSpouse) {
            return [
                'amount' => self::FAMILY_DISCOUNT_COUPLE,
                'type'   => 'couple',
                'label'  => 'خصم زوج وزوجة بالعضوية الموسمية في نفس الفترة',
            ];
        }

        // Parent + child under 15 = 500 off
        if ($hasMember && $childrenUnder15 > 0) {
            return [
                'amount' => self::FAMILY_DISCOUNT_PARENT_CHILD,
                'type'   => 'parent_child',
                'label'  => 'خصم والد/ة مع ابن أقل من 15 عام في نفس الفترة',
            ];
        }

        return ['amount' => '0.00', 'type' => null, 'label' => null];
    }

    public static function calculateNoQualificationDiscount(string $subtotal, bool $hasQualification): string
    {
        if ($hasQualification) return '0.00';
        return bcdiv(bcmul($subtotal, self::NO_QUALIFICATION_DISCOUNT_PCT, 4), '100', 2);
    }

    /**
     * Calculate full pricing for a seasonal subscription batch (member + family).
     *
     * @param array $items Each item: ['person_type' => member|spouse|child, 'age' => int|null, 'name' => string]
     * @param string $nationalityType 'egyptian' or 'foreign'
     * @param int $durationMonths 3, 6, or 12
     * @param bool $hasQualification Whether the main member holds a higher qualification
     * @return array Full breakdown with subtotals, VAT, discounts, total
     */
    public static function calculate(array $items, string $nationalityType, int $durationMonths, bool $hasQualification = true): array
    {
        $currency = $nationalityType === 'foreign' ? 'USD' : 'EGP';
        $lineItems = [];
        $subtotal = '0.00';

        foreach ($items as $item) {
            $personType = $item['person_type'];
            $age = $item['age'] ?? null;
            $ageCategory = null;

            if ($personType === 'member' && $age !== null && $age >= 60) {
                $ageCategory = 'over_60';
            } elseif ($personType === 'child' && $age !== null) {
                $ageCategory = self::getAgeCategory($age);
            }

            $price = self::getBasePrice($nationalityType, $durationMonths, $personType, $ageCategory);

            $lineItems[] = [
                'person_type'  => $personType,
                'person_name'  => $item['name'] ?? '',
                'age'          => $age,
                'age_category' => $ageCategory,
                'base_price'   => $price,
            ];

            $subtotal = bcadd($subtotal, $price, 2);
        }

        // Family discount (only for EGP)
        $familyDiscount = ['amount' => '0.00', 'type' => null, 'label' => null];
        if ($nationalityType === 'egyptian') {
            $familyDiscount = self::calculateFamilyDiscount($lineItems);
        }

        // No-qualification discount (only for EGP, only if no family discount already applied)
        $qualDiscount = '0.00';
        if ($nationalityType === 'egyptian' && $familyDiscount['type'] === null && !$hasQualification) {
            $qualDiscount = self::calculateNoQualificationDiscount($subtotal, $hasQualification);
        }

        $totalDiscount = bcadd($familyDiscount['amount'], $qualDiscount, 2);
        $afterDiscount = bcsub($subtotal, $totalDiscount, 2);
        if (bccomp($afterDiscount, '0', 2) < 0) $afterDiscount = '0.00';

        // VAT
        $vatAmount = self::calculateVat($afterDiscount);
        $grandTotal = bcadd($afterDiscount, $vatAmount, 2);

        return [
            'items'            => $lineItems,
            'subtotal'         => $subtotal,
            'family_discount'  => $familyDiscount,
            'qual_discount'    => $qualDiscount,
            'total_discount'   => $totalDiscount,
            'after_discount'   => $afterDiscount,
            'vat_rate'         => self::getVatRate(),
            'vat_amount'       => $vatAmount,
            'grand_total'      => $grandTotal,
            'currency'         => $currency,
            'duration_months'  => $durationMonths,
            'nationality_type' => $nationalityType,
            'includes_pool'    => true,
        ];
    }

    public static function getPricingTable(string $nationalityType): array
    {
        if ($nationalityType === 'foreign') {
            return self::FOREIGN_PRICES;
        }
        return self::EGYPTIAN_PRICES;
    }

    public static function getCategoryLabel(string $category): string
    {
        return match ($category) {
            'member'   => 'العضو',
            'spouse'   => 'الزوجة',
            'under_15' => 'أبناء أقل من 15 عام',
            '15_to_21' => 'أبناء أكثر من 15 عام وأقل من 21 عام',
            'over_21'  => 'أبناء أكثر من 21 عام',
            'over_60'  => 'العضو أكثر من 60 عام',
            default    => $category,
        };
    }
}
