<?php
declare(strict_types=1);

namespace App\Modules\Pricing\Services;

use App\Core\App;
use App\Core\Logger;
use App\Modules\Pricing\Models\RegulatoryDiscount;

final class RegulatoryDiscountService
{
    /**
     * Evaluate all applicable regulatory discounts for a membership application.
     *
     * @param array $context Keys: target_branch_id, source_branch_id (if existing member),
     *                       is_government_employee, is_ministry_youth_employee,
     *                       is_board_of_trustees, is_club_employee, employee_years,
     *                       group_quantity, membership_fee
     * @return array List of applicable discounts with calculated amounts
     */
    public static function evaluateEligibility(array $context): array
    {
        $applicable = [];

        $targetBranchId = (int) ($context['target_branch_id'] ?? 0);
        $sourceBranchId = (int) ($context['source_branch_id'] ?? 0);
        $membershipFee = (string) ($context['membership_fee'] ?? '0');

        // Cross-branch member discount (Article 97)
        if ($sourceBranchId > 0 && $targetBranchId > 0 && $sourceBranchId !== $targetBranchId) {
            $rules = RegulatoryDiscount::getActiveByType('cross_branch_member', $targetBranchId);
            foreach ($rules as $rule) {
                if ((int) $rule['source_branch_id'] === $sourceBranchId) {
                    $applicable[] = self::buildResult($rule, $membershipFee);
                }
            }
        }

        // Government employee discount (Article 98)
        if (!empty($context['is_government_employee'])) {
            $rules = RegulatoryDiscount::getActiveByType('government_employee', $targetBranchId);
            foreach ($rules as $rule) {
                $applicable[] = self::buildResult($rule, $membershipFee);
            }
        }

        // Ministry of Youth employee discount (Articles 98, 99)
        if (!empty($context['is_ministry_youth_employee'])) {
            $rules = RegulatoryDiscount::getActiveByType('ministry_youth_employee', $targetBranchId);
            foreach ($rules as $rule) {
                $applicable[] = self::buildResult($rule, $membershipFee);
            }
        }

        // Board of Trustees discount (Article 100)
        if (!empty($context['is_board_of_trustees'])) {
            $rules = RegulatoryDiscount::getActiveByType('board_of_trustees', $targetBranchId);
            foreach ($rules as $rule) {
                $applicable[] = self::buildResult($rule, $membershipFee);
            }
        }

        // Club employee discount (Article 102)
        if (!empty($context['is_club_employee'])) {
            $employeeYears = (int) ($context['employee_years'] ?? 0);
            $rules = RegulatoryDiscount::getActiveByType('club_employee', $targetBranchId);
            foreach ($rules as $rule) {
                $minYears = (int) ($rule['min_service_years'] ?? 0);
                if ($employeeYears >= $minYears) {
                    $applicable[] = self::buildResult($rule, $membershipFee);
                }
            }
        }

        // Group membership discount (Article 110)
        $groupQty = (int) ($context['group_quantity'] ?? 0);
        if ($groupQty >= 5) {
            $rules = RegulatoryDiscount::getActiveByType('group_membership', $targetBranchId);
            foreach ($rules as $rule) {
                $tier = self::getGroupTier((int) $rule['id'], $groupQty);
                if ($tier) {
                    $result = self::buildResult($rule, $membershipFee, (string) $tier['discount_percentage']);
                    $result['tier'] = $tier;
                    $result['group_quantity'] = $groupQty;
                    $applicable[] = $result;
                }
            }
        }

        return $applicable;
    }

    /**
     * Get the best single discount for a given context (non-stackable — take highest).
     */
    public static function getBestDiscount(array $context): ?array
    {
        $applicable = self::evaluateEligibility($context);
        if (empty($applicable)) {
            return null;
        }

        usort($applicable, function ($a, $b) {
            return bccomp($b['discount_amount'], $a['discount_amount'], 2);
        });

        return $applicable[0];
    }

    /**
     * Create an application record for audit trail.
     */
    public static function createApplication(array $data): int
    {
        $db = App::getInstance()->db();
        return $db->insert('regulatory_discount_applications', [
            'regulatory_discount_id' => $data['regulatory_discount_id'],
            'member_id'              => $data['member_id'] ?? null,
            'applicant_name'         => $data['applicant_name'] ?? null,
            'discount_percentage'    => $data['discount_percentage'],
            'original_amount'        => $data['original_amount'],
            'discount_amount'        => $data['discount_amount'],
            'final_amount'           => $data['final_amount'],
            'status'                 => $data['status'] ?? 'pending',
            'verification_data'      => isset($data['verification_data']) ? json_encode($data['verification_data']) : null,
            'notes'                  => $data['notes'] ?? null,
            'created_by'             => $data['created_by'] ?? null,
        ]);
    }

    /**
     * Approve a pending discount application.
     */
    public static function approveApplication(int $applicationId, int $approvedBy): bool
    {
        $db = App::getInstance()->db();
        $app = $db->selectOne("SELECT * FROM regulatory_discount_applications WHERE id = ?", [$applicationId]);
        if (!$app || $app['status'] !== 'pending') {
            return false;
        }

        $db->update('regulatory_discount_applications', [
            'status'      => 'approved',
            'approved_by' => $approvedBy,
            'approved_at' => date('Y-m-d H:i:s'),
        ], 'id = ?', [$applicationId]);

        return true;
    }

    /**
     * Verify club employee eligibility by checking HR records.
     */
    public static function verifyClubEmployee(int $employeeId): array
    {
        $db = App::getInstance()->db();
        $profile = $db->selectOne(
            "SELECT employee_id, first_name_ar, last_name_ar, hire_date, employment_status FROM hr_employee_profiles WHERE employee_id = ? AND is_archived = 0",
            [$employeeId]
        );

        if (!$profile || $profile['employment_status'] !== 'active') {
            return ['eligible' => false, 'reason' => 'الموظف غير نشط أو غير موجود'];
        }

        $hireDate = new \DateTime($profile['hire_date']);
        $now = new \DateTime();
        $years = (int) $now->diff($hireDate)->y;

        return [
            'eligible'      => true,
            'employee_name' => $profile['first_name_ar'] . ' ' . $profile['last_name_ar'],
            'hire_date'     => $profile['hire_date'],
            'service_years' => $years,
        ];
    }

    /**
     * Verify existing membership in another branch (for cross-branch discount).
     */
    public static function verifyCrossBranchMembership(int $memberId, int $sourceBranchId): array
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne(
            "SELECT m.id, m.member_number, m.full_name_ar, m.branch_id, b.name_ar as branch_name FROM members m LEFT JOIN branches b ON b.id = m.branch_id WHERE m.id = ? AND m.branch_id = ? AND m.status = 'active'",
            [$memberId, $sourceBranchId]
        );

        if (!$member) {
            return ['eligible' => false, 'reason' => 'لا توجد عضوية نشطة في الفرع المصدر'];
        }

        return [
            'eligible'      => true,
            'member_number' => $member['member_number'],
            'member_name'   => $member['full_name_ar'],
            'branch_name'   => $member['branch_name'],
        ];
    }

    private static function buildResult(array $rule, string $membershipFee, ?string $overridePercentage = null): array
    {
        $pct = $overridePercentage ?? $rule['discount_percentage'];

        if ($rule['max_discount_percentage'] !== null) {
            $pct = min((float) $pct, (float) $rule['max_discount_percentage']);
            $pct = number_format($pct, 2, '.', '');
        }

        $discountAmount = bcmul($membershipFee, bcdiv($pct, '100', 4), 2);
        $finalAmount = bcsub($membershipFee, $discountAmount, 2);

        return [
            'rule_id'             => (int) $rule['id'],
            'article_number'      => $rule['article_number'],
            'name_ar'             => $rule['name_ar'],
            'eligibility_type'    => $rule['eligibility_type'],
            'discount_percentage' => $pct,
            'original_amount'     => $membershipFee,
            'discount_amount'     => $discountAmount,
            'final_amount'        => $finalAmount,
            'allows_installment'  => (bool) $rule['allows_installment'],
            'installment_max_years' => $rule['installment_max_years'] ? (int) $rule['installment_max_years'] : null,
            'installment_interest_rate' => $rule['installment_interest_rate'],
        ];
    }

    private static function getGroupTier(int $discountId, int $quantity): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne(
            "SELECT * FROM regulatory_discount_group_tiers WHERE regulatory_discount_id = ? AND is_active = 1 AND min_quantity <= ? AND (max_quantity IS NULL OR max_quantity >= ?) ORDER BY min_quantity DESC LIMIT 1",
            [$discountId, $quantity, $quantity]
        );
    }
}
