<?php
declare(strict_types=1);

namespace App\Modules\Spouses\Services;

use App\Core\App;
use App\Modules\Spouses\Models\Spouse;
use App\Modules\Rules\Services\RuleEngine;
use App\Modules\Members\Services\FormFeeService;

/**
 * Spouse Fee Calculator — all percentages/amounts read from RuleEngine.
 *
 * RULES (editable via /rules admin):
 *   1st Spouse (initial form, not foreign):    FREE (INITIAL_FREE_SPOUSES_COUNT)
 *   1st Spouse (late, basic member):           SPOUSE_BASE_MEMBER_FEE %
 *   1st Spouse (late, acquired member):        SPOUSE_ACQUIRED_MEMBER_FEE %
 *   Foreign Spouse:                            SPOUSE_FOREIGN_FEE %
 *   2nd Spouse:  SPOUSE_2ND_FEE  (percentage + annual_flat × years)
 *   3rd Spouse:  SPOUSE_3RD_FEE  (percentage + annual_flat × years)
 *   4th+ Spouse: SPOUSE_4TH_FEE  (percentage + annual_flat × years)
 *   Late addition form fee:                    FORM_ADDITION_FEE (shared via FormFeeService)
 */
final class SpouseFeeCalculator
{
    public static function calculate(int $memberId, array $spouseData): array
    {
        $db = App::getInstance()->db();

        $member = $db->selectOne("SELECT * FROM members WHERE id = ? AND is_archived = 0", [$memberId]);
        if (!$member) {
            return self::error('العضو غير موجود');
        }

        $membershipValue = $member['membership_value'] ?? '0.00';
        $isOnInitialForm = FormFeeService::isOnInitialForm($member);

        // Foreign membership: spouse + 3 children included in the $10k fee — no extra charges
        if (($member['membership_type'] ?? 'working') === 'foreign' && $isOnInitialForm) {
            $existingCount = Spouse::countActiveForMember($memberId);
            $spouseOrder = $existingCount + 1;
            return [
                'spouse_order'          => $spouseOrder,
                'membership_value'      => '0.00',
                'is_initial'            => true,
                'is_late_addition'      => false,
                'is_acquired'           => false,
                'is_foreign'            => false,
                'percentage'            => '0.00',
                'percentage_fee'        => '0.00',
                'annual_per_year'       => '0.00',
                'year_count'            => 0,
                'yearly_total'          => '0.00',
                'addition_fee'          => '0.00',
                'form_fee'              => '0.00',
                'annual_subscription'   => '0.00',
                'total_fee'             => '0.00',
                'rule_applied'          => 'العضوية الأجنبية — الزوج/ة مشمول/ة في رسوم العضوية',
                'error'                 => null,
                'breakdown'             => ['✅ مشمول/ة في رسوم العضوية الأجنبية — بدون رسوم إضافية'],
            ];
        }

        // Always use current membership value from pricing_configs
        $qualId = !empty($member['qualification_id']) ? (int) $member['qualification_id'] : null;
        $branchId = (int) ($member['branch_id'] ?? 1);
        $mType = $member['membership_type'] ?? 'working';
        if ($qualId) {
            $currentPricing = $db->selectOne(
                "SELECT price FROM pricing_configs WHERE branch_id = ? AND qualification_id = ? AND membership_type = ? AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY effective_from DESC LIMIT 1",
                [$branchId, $qualId, $mType]
            );
        } else {
            $currentPricing = $db->selectOne(
                "SELECT price FROM pricing_configs WHERE branch_id = ? AND membership_type = ? AND is_active = 1 AND effective_from <= CURDATE() AND (effective_to IS NULL OR effective_to >= CURDATE()) ORDER BY price ASC LIMIT 1",
                [$branchId, $mType]
            );
        }
        if ($currentPricing && bccomp($currentPricing['price'], '0.01', 2) >= 0) {
            $membershipValue = $currentPricing['price'];
        }

        if (bccomp($membershipValue, '0.01', 2) < 0 && !$isOnInitialForm) {
            return self::error('يجب تحديد قيمة العضوية أولاً (ملء الاستمارة واختيار المؤهل)');
        }

        $existingCount = Spouse::countActiveForMember($memberId);
        $spouseOrder = $existingCount + 1;

        $isInitialCreation = $isOnInitialForm;
        $isFreeSlot = FormFeeService::isSpouseFreeSlot($memberId, $spouseOrder);

        // On initial form with no value yet: allow adding — fees recalculated via BillingService when form is filled
        if (bccomp($membershipValue, '0.01', 2) < 0 && $isOnInitialForm && !$isFreeSlot) {
            return [
                'spouse_order'          => $spouseOrder,
                'membership_value'      => '0.00',
                'is_initial'            => true,
                'is_late_addition'      => false,
                'is_acquired'           => false,
                'is_foreign'            => false,
                'percentage'            => '0.00',
                'percentage_fee'        => '0.00',
                'annual_per_year'       => '0.00',
                'year_count'            => 0,
                'yearly_total'          => '0.00',
                'addition_fee'          => '0.00',
                'form_fee'              => '0.00',
                'annual_subscription'   => '0.00',
                'total_fee'             => '0.00',
                'rule_applied'          => 'في انتظار ملء الاستمارة — سيُحسب تلقائياً عند تحديد المؤهل',
                'pending_calculation'   => true,
                'error'                 => null,
                'breakdown'             => ['⏳ الرسوم ستُحسب تلقائياً بعد ملء الاستمارة واختيار المؤهل'],
            ];
        }

        $formFeeOnly = FormFeeService::getFormFeeOnly($memberId, $member);
        $annualSubscription = '0.00';
        if (!$isOnInitialForm) {
            $spouseSubRate = $db->selectOne(
                "SELECT base_amount FROM service_catalog WHERE service_code LIKE 'SVC_ANNUAL_SPOUSE%' AND is_active = 1 ORDER BY effective_from DESC LIMIT 1"
            );
            $annualSubscription = $spouseSubRate ? $spouseSubRate['base_amount'] : '492.00';
        }
        $formFee = bcadd($formFeeOnly, $annualSubscription, 2);

        $isAcquiredMember = self::isAcquiredMember($memberId);

        $nationality = trim($spouseData['nationality'] ?? 'مصري');
        $isForeign = ($nationality !== 'مصري' && $nationality !== '' && $nationality !== 'Egyptian');

        $marriageDate = $spouseData['marriage_date'] ?? null;
        $memberCreatedDate = substr($member['created_at'] ?? date('Y-m-d'), 0, 10);
        $memberActivatedDate = !empty($member['activated_at']) ? substr($member['activated_at'], 0, 10) : $memberCreatedDate;

        $percentage = '0.00';
        $percentageFee = '0.00';
        $annualPerYear = '0.00';
        $yearCount = 0;
        $yearlyTotal = '0.00';
        $ruleApplied = '';

        switch (true) {
            case ($spouseOrder === 1):
                if ($isFreeSlot && !$isForeign) {
                    $percentage = '0.00';
                    if ($isInitialCreation) {
                        $ruleApplied = 'الزوجة الأولى — مشمولة في الاستمارة الأولى (بدون رسوم)';
                    } else {
                        $ruleApplied = 'الزوجة الأولى — مشمولة (رسوم الاستمارة فقط ' . money($formFee) . ')';
                    }
                } elseif ($isForeign) {
                    $data = RuleEngine::require('SPOUSE_FOREIGN_FEE');
                    $percentage = $data['percentage'];
                    $ruleApplied = 'زوج/ة أجنبي — ' . $percentage . '% من قيمة العضوية';
                } elseif ($isAcquiredMember) {
                    $data = RuleEngine::require('SPOUSE_ACQUIRED_MEMBER_FEE');
                    $percentage = $data['percentage'];
                    $ruleApplied = 'إضافة زوج/ة لعضو مكتسب العضوية (فصل/طلاق/وفاة/تنازل) — ' . $percentage . '% من قيمة العضوية';
                } else {
                    $data = RuleEngine::require('SPOUSE_BASE_MEMBER_FEE');
                    $percentage = $data['percentage'];
                    $ruleApplied = 'إضافة زوج/ة لعضو أساس العضوية (إضافة لاحقة) — ' . $percentage . '% من قيمة العضوية';
                }
                $percentageFee = bcdiv(bcmul($membershipValue, $percentage, 4), '100', 2);
                break;

            case ($spouseOrder === 2):
                $data = RuleEngine::require('SPOUSE_2ND_FEE');
                $percentage = $data['percentage'];
                $annualPerYear = $data['annual_flat'];
                $percentageFee = bcdiv(bcmul($membershipValue, $percentage, 4), '100', 2);
                if ($isInitialCreation) {
                    $ruleApplied = 'الزوجة الثانية — ' . $percentage . '% من قيمة العضوية (بدون غرامات — استمارة أولى)';
                } else {
                    $ruleApplied = 'الزوجة الثانية — ' . $percentage . '% من قيمة العضوية + ' . $annualPerYear . ' ج.م عن كل سنة';
                    $yearCount = self::calculateYears($marriageDate, $memberActivatedDate);
                    $yearlyTotal = bcmul($annualPerYear, (string) $yearCount, 2);
                }
                break;

            case ($spouseOrder === 3):
                $data = RuleEngine::require('SPOUSE_3RD_FEE');
                $percentage = $data['percentage'];
                $annualPerYear = $data['annual_flat'];
                $percentageFee = bcdiv(bcmul($membershipValue, $percentage, 4), '100', 2);
                if ($isInitialCreation) {
                    $ruleApplied = 'الزوجة الثالثة — ' . $percentage . '% من قيمة العضوية (بدون غرامات — استمارة أولى)';
                } else {
                    $ruleApplied = 'الزوجة الثالثة — ' . $percentage . '% من قيمة العضوية + ' . $annualPerYear . ' ج.م عن كل سنة';
                    $yearCount = self::calculateYears($marriageDate, $memberActivatedDate);
                    $yearlyTotal = bcmul($annualPerYear, (string) $yearCount, 2);
                }
                break;

            case ($spouseOrder >= 4):
                $data = RuleEngine::require('SPOUSE_4TH_FEE');
                $percentage = $data['percentage'];
                $annualPerYear = $data['annual_flat'];
                $percentageFee = bcdiv(bcmul($membershipValue, $percentage, 4), '100', 2);
                if ($isInitialCreation) {
                    $ruleApplied = 'الزوجة الرابعة — ' . $percentage . '% من قيمة العضوية (بدون غرامات — استمارة أولى)';
                } else {
                    $ruleApplied = 'الزوجة الرابعة — ' . $percentage . '% من قيمة العضوية + ' . $annualPerYear . ' ج.م عن كل سنة';
                    $yearCount = self::calculateYears($marriageDate, $memberActivatedDate);
                    $yearlyTotal = bcmul($annualPerYear, (string) $yearCount, 2);
                }
                break;
        }

        $additionFee = bcadd($percentageFee, $yearlyTotal, 2);
        $totalFee = bcadd($additionFee, $formFee, 2);

        if ($spouseOrder >= 2 && bccomp($additionFee, '0.01', 2) < 0) {
            return self::error(
                'خطأ في حساب الرسوم — الزوجة رقم ' . $spouseOrder .
                ' يجب أن تكون برسوم. قيمة العضوية: ' . money($membershipValue)
            );
        }

        return [
            'spouse_order'          => $spouseOrder,
            'membership_value'      => $membershipValue,
            'is_initial'            => $isInitialCreation,
            'is_late_addition'      => !$isInitialCreation,
            'is_acquired'           => $isAcquiredMember,
            'is_foreign'            => $isForeign,
            'percentage'            => $percentage,
            'percentage_fee'        => $percentageFee,
            'annual_per_year'       => $annualPerYear,
            'year_count'            => $yearCount,
            'yearly_total'          => $yearlyTotal,
            'addition_fee'          => $additionFee,
            'form_fee'              => $formFeeOnly,
            'annual_subscription'   => $annualSubscription,
            'total_fee'             => $totalFee,
            'rule_applied'          => $ruleApplied,
            'error'                 => null,
            'breakdown'             => self::buildBreakdown(
                $spouseOrder, $membershipValue, $percentage, $percentageFee,
                $annualPerYear, $yearCount, $yearlyTotal,
                $formFeeOnly, $annualSubscription, $totalFee, $ruleApplied, $isFreeSlot && !$isForeign
            ),
        ];
    }

    private static function calculateYears(?string $marriageDate, string $memberActivatedDate): int
    {
        if (!$marriageDate) {
            return 0;
        }

        $marriageTs = strtotime($marriageDate);
        $memberTs = strtotime($memberActivatedDate);

        if (!$marriageTs || !$memberTs) {
            return 0;
        }

        // Start counting from LATER of marriage or membership activation
        $startTs = max($marriageTs, $memberTs);
        $start = new \DateTime(date('Y-m-d', $startTs));
        $end = new \DateTime(); // today

        $diff = $end->diff($start);
        $years = $diff->y;

        // Partial year counts as full year
        if ($diff->m > 0 || $diff->d > 0) {
            $years++;
        }

        return max(0, $years);
    }

    private static function isAcquiredMember(int $memberId): bool
    {
        $db = App::getInstance()->db();

        $row = $db->selectOne(
            "SELECT id FROM members WHERE id = ? AND (
                transferred_from_transfer_id IS NOT NULL
                OR transferred_from_death_id IS NOT NULL
                OR transferred_from_waiver_id IS NOT NULL
                OR transferred_from_divorce_id IS NOT NULL
            ) LIMIT 1",
            [$memberId]
        );

        return $row !== null && $row !== false;
    }

    private static function buildBreakdown(
        int $order, string $membershipValue, string $pct, string $pctFee,
        string $annual, int $years, string $yearlyTotal,
        string $formFee, string $annualSubscription, string $totalFee, string $rule, bool $isFirstFree
    ): array {
        $lines = [];
        $lines[] = '📋 القاعدة المطبقة: ' . $rule;
        $lines[] = '💰 قيمة العضوية: ' . money($membershipValue);

        if ($isFirstFree && bccomp($formFee, '0', 2) <= 0 && bccomp($annualSubscription, '0', 2) <= 0) {
            $lines[] = '✅ الزوجة الأولى مشمولة في الاستمارة — بدون رسوم إضافية';
        } elseif ($isFirstFree) {
            $lines[] = '✅ الزوجة الأولى مشمولة (بدون رسوم عضوية)';
            if (bccomp($formFee, '0', 2) > 0) {
                $lines[] = '📝 رسوم استمارة إضافة: ' . money($formFee);
            }
            if (bccomp($annualSubscription, '0', 2) > 0) {
                $lines[] = '📅 اشتراك سنوي: ' . money($annualSubscription);
            }
        } else {
            if (bccomp($pctFee, '0', 2) > 0) {
                $lines[] = "📊 نسبة {$pct}% × " . money($membershipValue) . ' = ' . money($pctFee);
            }
            if (bccomp($annual, '0', 2) > 0 && $years > 0) {
                $lines[] = "📅 غرامة تأخير إضافة: {$annual} ج.م × {$years} سنة = " . money($yearlyTotal);
                $lines[] = '   (تحسب من الأحدث بين تاريخ الزواج أو العضوية حتى اليوم — كسر السنة سنة كاملة)';
            }
            if (bccomp($formFee, '0', 2) > 0) {
                $lines[] = '📝 رسوم استمارة إضافة: ' . money($formFee);
            }
            if (bccomp($annualSubscription, '0', 2) > 0) {
                $lines[] = '📅 اشتراك سنوي: ' . money($annualSubscription);
            }
        }

        $lines[] = '═══════════════════════════';
        $lines[] = '💵 الإجمالي المطلوب: ' . money($totalFee);

        return $lines;
    }

    private static function error(string $message): array
    {
        return [
            'spouse_order'        => 0,
            'membership_value'    => '0.00',
            'percentage'          => '0.00',
            'percentage_fee'      => '0.00',
            'annual_per_year'     => '0.00',
            'year_count'          => 0,
            'yearly_total'        => '0.00',
            'addition_fee'        => '0.00',
            'form_fee'            => '0.00',
            'annual_subscription' => '0.00',
            'total_fee'           => '0.00',
            'rule_applied'        => '',
            'error'               => $message,
            'breakdown'           => ['❌ ' . $message],
        ];
    }
}
