<?php
declare(strict_types=1);

namespace App\Modules\Pricing\Services;

use App\Core\App;
use App\Core\Logger;

final class SpecialDiscountService
{
    /**
     * Evaluate which discounts apply to a member based on their payment context.
     * Called during billing to calculate applicable discount amount.
     *
     * @return array{discount_amount: string, discount_label: string, bonus_free_years: int, discount_id: int|null}
     */
    public static function evaluateForMember(int $memberId, string $membershipValue, string $totalPaid = '0.00'): array
    {
        $db = App::getInstance()->db();
        $today = date('Y-m-d');

        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [$memberId]);
        if (!$member) {
            return self::emptyResult();
        }

        // If the member has a specific discount assigned, use that
        if (!empty($member['special_discount_id'])) {
            $discount = $db->selectOne(
                "SELECT * FROM special_discounts WHERE id = ? AND is_active = 1",
                [(int) $member['special_discount_id']]
            );
            if ($discount) {
                if (self::isWithinDateRange($discount, $today)) {
                    return self::calculateDiscount($discount, $membershipValue, $totalPaid);
                }
            }
        }

        // Check for auto-applicable conditional discounts (full_payment, min_payment)
        $conditionalDiscounts = $db->select(
            "SELECT * FROM special_discounts WHERE is_active = 1 AND condition_type != 'none' AND (effective_from IS NULL OR effective_from <= ?) AND (effective_to IS NULL OR effective_to >= ?) ORDER BY discount_percentage DESC",
            [$today, $today]
        );

        foreach ($conditionalDiscounts as $discount) {
            if (self::conditionMet($discount, $membershipValue, $totalPaid)) {
                return self::calculateDiscount($discount, $membershipValue, $totalPaid);
            }
        }

        return self::emptyResult();
    }

    /**
     * Check if a member qualifies for bonus free subscription years.
     * Called after a membership_fee payment is completed.
     */
    public static function getBonusFreeYears(int $memberId): int
    {
        $db = App::getInstance()->db();
        $today = date('Y-m-d');

        $member = $db->selectOne("SELECT special_discount_id, membership_value FROM members WHERE id = ?", [$memberId]);
        if (!$member || empty($member['special_discount_id'])) {
            // Check conditional discounts
            $membershipValue = $member['membership_value'] ?? '0.00';
            $totalPaid = self::getTotalMembershipPaid($db, $memberId);
            $conditionalDiscounts = $db->select(
                "SELECT * FROM special_discounts WHERE is_active = 1 AND condition_type != 'none' AND bonus_free_subscription_years > 0 AND (effective_from IS NULL OR effective_from <= ?) AND (effective_to IS NULL OR effective_to >= ?)",
                [$today, $today]
            );
            foreach ($conditionalDiscounts as $d) {
                if (self::conditionMet($d, $membershipValue, $totalPaid)) {
                    return (int) $d['bonus_free_subscription_years'];
                }
            }
            return 0;
        }

        $discount = $db->selectOne(
            "SELECT * FROM special_discounts WHERE id = ? AND is_active = 1 AND bonus_free_subscription_years > 0",
            [(int) $member['special_discount_id']]
        );

        if (!$discount || !self::isWithinDateRange($discount, $today)) {
            return 0;
        }

        return (int) $discount['bonus_free_subscription_years'];
    }

    /**
     * Apply free subscription bonus: mark N years of subscriptions as paid (discount = 100%).
     */
    public static function applyFreeSubscriptionBonus(int $memberId, int $freeYears): void
    {
        if ($freeYears <= 0) return;

        $db = App::getInstance()->db();
        $currentFy = financial_year();

        $pendingSubs = $db->select(
            "SELECT id, financial_year, total_amount FROM subscriptions WHERE member_id = ? AND status = 'pending' ORDER BY financial_year ASC LIMIT ?",
            [$memberId, $freeYears * 10]
        );

        $yearsMarked = 0;
        $lastFy = '';
        foreach ($pendingSubs as $sub) {
            if ($sub['financial_year'] !== $lastFy) {
                $yearsMarked++;
                $lastFy = $sub['financial_year'];
                if ($yearsMarked > $freeYears) break;
            }
            $db->update('subscriptions', [
                'status'          => 'paid',
                'discount_amount' => $sub['total_amount'],
                'total_amount'    => '0.00',
                'paid_at'         => date('Y-m-d H:i:s'),
                'updated_at'      => date('Y-m-d H:i:s'),
                'receipt_number'  => 'FREE-BONUS',
            ], '`id` = ?', [(int) $sub['id']]);
        }

        if ($yearsMarked > 0) {
            Logger::info("SpecialDiscountService: applied {$yearsMarked} free subscription year(s) for member #{$memberId}");
        }
    }

    private static function conditionMet(array $discount, string $membershipValue, string $totalPaid): bool
    {
        $conditionType = $discount['condition_type'] ?? 'none';

        if ($conditionType === 'full_payment') {
            return bccomp($membershipValue, '0.01', 2) >= 0 && bccomp($totalPaid, $membershipValue, 2) >= 0;
        }

        if ($conditionType === 'min_payment') {
            $minAmount = $discount['condition_min_amount'] ?? '0.00';
            return bccomp($totalPaid, $minAmount, 2) >= 0;
        }

        return false;
    }

    private static function calculateDiscount(array $discount, string $membershipValue, string $totalPaid): array
    {
        $type = $discount['discount_type'] ?? 'percentage';
        $discountAmount = '0.00';

        if ($type === 'percentage') {
            $pct = $discount['discount_percentage'] ?? '0.00';
            $discountAmount = bcdiv(bcmul($membershipValue, $pct, 4), '100', 2);
        } elseif ($type === 'fixed_amount') {
            $discountAmount = $discount['fixed_amount'] ?? '0.00';
        } elseif ($type === 'free_subscription') {
            $discountAmount = '0.00';
        }

        return [
            'discount_amount' => $discountAmount,
            'discount_label'  => $discount['name_ar'] ?? 'خصم خاص',
            'discount_id'     => (int) $discount['id'],
            'discount_type'   => $type,
            'percentage'      => $discount['discount_percentage'] ?? '0.00',
            'bonus_free_years'=> (int) ($discount['bonus_free_subscription_years'] ?? 0),
            'applies_to'      => $discount['applies_to'] ?? 'membership_fee',
        ];
    }

    private static function isWithinDateRange(array $discount, string $today): bool
    {
        $from = $discount['effective_from'] ?? null;
        $to = $discount['effective_to'] ?? null;

        if ($from && $today < $from) return false;
        if ($to && $today > $to) return false;

        return true;
    }

    private static function getTotalMembershipPaid(\App\Core\Database $db, int $memberId): string
    {
        $row = $db->selectOne(
            "SELECT COALESCE(SUM(amount), 0) as total FROM payments WHERE member_id = ? AND payment_type IN ('membership_fee', 'down_payment') AND is_voided = 0",
            [$memberId]
        );
        return $row['total'] ?? '0.00';
    }

    private static function emptyResult(): array
    {
        return [
            'discount_amount' => '0.00',
            'discount_label'  => '',
            'discount_id'     => null,
            'discount_type'   => null,
            'percentage'      => '0.00',
            'bonus_free_years'=> 0,
            'applies_to'      => 'membership_fee',
        ];
    }
}
