<?php
declare(strict_types=1);

namespace App\Modules\Members\Services;

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

final class BoardOfferService
{
    public static function getActiveOffers(?int $branchId = null): array
    {
        $db = App::getInstance()->db();
        $today = date('Y-m-d');

        $where = "`is_active` = 1 AND `effective_from` <= ? AND `effective_to` >= ?";
        $params = [$today, $today];

        if ($branchId !== null) {
            $where .= " AND (`branch_id` IS NULL OR `branch_id` = ?)";
            $params[] = $branchId;
        }

        return $db->select(
            "SELECT * FROM `board_offers` WHERE {$where} ORDER BY `branch_id` DESC, `effective_from` DESC",
            $params
        );
    }

    public static function getBestOffer(?int $branchId = null): ?array
    {
        $offers = self::getActiveOffers($branchId);
        if (empty($offers)) {
            return null;
        }
        return $offers[0];
    }

    public static function getOfferTiers(int $offerId): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT * FROM `board_offer_tiers` WHERE `board_offer_id` = ? AND `is_active` = 1 ORDER BY `tier_order` ASC",
            [$offerId]
        );
    }

    public static function getTierById(int $tierId): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne(
            "SELECT t.*, o.is_active AS offer_active, o.effective_from, o.effective_to, o.title_ar AS offer_title
             FROM `board_offer_tiers` t
             JOIN `board_offers` o ON o.id = t.board_offer_id
             WHERE t.id = ? AND t.is_active = 1",
            [$tierId]
        ) ?: null;
    }

    public static function calculateTierBreakdown(array $tier, string $totalAmount): array
    {
        if ($tier['payment_type'] === 'cash') {
            $discountPct = (string) ($tier['cash_discount_pct'] ?? '0');
            $savings = bcdiv(bcmul($totalAmount, $discountPct, 4), '100', 2);
            $afterDiscount = bcsub($totalAmount, $savings, 2);
            return [
                'payment_type'   => 'cash',
                'original'       => $totalAmount,
                'discount_pct'   => $discountPct,
                'savings'        => $savings,
                'amount_due'     => $afterDiscount,
                'down_payment'   => $afterDiscount,
                'months'         => 0,
                'interest_rate'  => '0.00',
                'interest_total' => '0.00',
                'monthly'        => '0.00',
                'grand_total'    => $afterDiscount,
            ];
        }

        $downPct = (string) ($tier['down_payment_pct'] ?? '25');
        $months = (int) ($tier['months'] ?? 24);
        $interestRate = (string) ($tier['interest_rate'] ?? '0');

        $downPayment = bcdiv(bcmul($totalAmount, $downPct, 4), '100', 2);
        $remaining = bcsub($totalAmount, $downPayment, 2);
        $interestTotal = bcmul(
            bcmul($remaining, bcdiv($interestRate, '100', 8), 8),
            bcdiv((string) $months, '12', 8),
            2
        );
        $totalWithInterest = bcadd($remaining, $interestTotal, 2);
        $monthly = $months > 0 ? bcdiv($totalWithInterest, (string) $months, 2) : '0.00';
        $grandTotal = bcadd($downPayment, $totalWithInterest, 2);

        return [
            'payment_type'   => 'installment',
            'original'       => $totalAmount,
            'discount_pct'   => '0.00',
            'savings'        => '0.00',
            'amount_due'     => $totalAmount,
            'down_payment'   => $downPayment,
            'down_pct'       => $downPct,
            'months'         => $months,
            'interest_rate'  => $interestRate,
            'interest_total' => $interestTotal,
            'remaining'      => $remaining,
            'monthly'        => $monthly,
            'grand_total'    => $grandTotal,
        ];
    }

    public static function getInstallmentTermsForTier(array $tier): array
    {
        return [
            'down_pct'      => (string) ($tier['down_payment_pct'] ?? '25.00'),
            'max_months'    => (int) ($tier['months'] ?? 24),
            'interest_rate' => (string) ($tier['interest_rate'] ?? '0.00'),
            'grace_type'    => null,
            'grace_months'  => 0,
        ];
    }

    public static function getCashDiscount(string $amount, ?array $offer = null): array
    {
        if ($offer === null) {
            $offer = self::getBestOffer();
        }

        if (!$offer || !$offer['cash_discount_type'] || !$offer['cash_discount_value']) {
            return [
                'original'   => $amount,
                'discounted' => $amount,
                'savings'    => '0.00',
                'type'       => null,
                'value'      => null,
                'offer'      => null,
            ];
        }

        $savings = '0.00';
        if ($offer['cash_discount_type'] === 'percentage') {
            $savings = bcdiv(bcmul($amount, (string) $offer['cash_discount_value'], 4), '100', 2);
        } else {
            $savings = (string) $offer['cash_discount_value'];
            if (bccomp($savings, $amount, 2) > 0) {
                $savings = $amount;
            }
        }

        $discounted = bcsub($amount, $savings, 2);
        if (bccomp($discounted, '0', 2) < 0) {
            $discounted = '0.00';
        }

        return [
            'original'   => $amount,
            'discounted' => $discounted,
            'savings'    => $savings,
            'type'       => $offer['cash_discount_type'],
            'value'      => $offer['cash_discount_value'],
            'offer'      => $offer,
        ];
    }

    public static function getInstallmentTerms(?array $offer = null): array
    {
        $interestData = RuleEngine::get('INSTALLMENT_INTEREST_RATE');
        $minDownData = RuleEngine::get('INSTALLMENT_MIN_DOWN_PAYMENT');
        $maxMonthsData = RuleEngine::get('INSTALLMENT_MAX_MONTHS');

        $defaults = [
            'down_pct'         => $minDownData['percentage'] ?? '25.00',
            'max_months'       => (int) ($maxMonthsData['months'] ?? 30),
            'interest_rate'    => $interestData['percentage'] ?? '22.00',
            'grace_type'       => null,
            'grace_months'     => 0,
            'post_grace_rate'  => null,
            'offer'            => null,
        ];

        if (!$offer) {
            return $defaults;
        }

        $terms = $defaults;
        $terms['offer'] = $offer;

        if ($offer['inst_down_payment_pct'] !== null) {
            $terms['down_pct'] = (string) $offer['inst_down_payment_pct'];
        }
        if ($offer['inst_months'] !== null) {
            $terms['max_months'] = (int) $offer['inst_months'];
        }
        if ($offer['inst_interest_rate'] !== null) {
            $terms['interest_rate'] = (string) $offer['inst_interest_rate'];
        }
        if ($offer['inst_grace_type'] !== null) {
            $terms['grace_type'] = $offer['inst_grace_type'];
            $terms['grace_months'] = (int) $offer['inst_grace_months'];
        }
        if ($offer['inst_post_grace_rate'] !== null) {
            $terms['post_grace_rate'] = (string) $offer['inst_post_grace_rate'];
        }

        return $terms;
    }

    public static function getInstallmentOverrides(): array
    {
        $offer = self::getBestOffer();
        if (!$offer) {
            return [];
        }

        $overrides = [];
        if ($offer['inst_months'] !== null) {
            $overrides['max_months'] = (int) $offer['inst_months'];
        }
        if ($offer['inst_interest_rate'] !== null) {
            $overrides['interest_rate'] = (string) $offer['inst_interest_rate'];
        }
        if ($offer['inst_down_payment_pct'] !== null) {
            $overrides['min_down_pct'] = (string) $offer['inst_down_payment_pct'];
        }
        if ($offer['inst_grace_type'] !== null) {
            $overrides['grace_type'] = $offer['inst_grace_type'];
            $overrides['grace_months'] = (int) $offer['inst_grace_months'];
            if ($offer['inst_post_grace_rate'] !== null) {
                $overrides['post_grace_rate'] = (string) $offer['inst_post_grace_rate'];
            }
        }

        $overrides['offer'] = $offer;
        return $overrides;
    }

    public static function snapshotOffer(array $offer, ?array $tier = null): string
    {
        $data = [
            'id'                    => $offer['id'],
            'title_ar'              => $offer['title_ar'],
            'cash_discount_type'    => $offer['cash_discount_type'],
            'cash_discount_value'   => $offer['cash_discount_value'],
            'inst_down_payment_pct' => $offer['inst_down_payment_pct'],
            'inst_months'           => $offer['inst_months'],
            'inst_interest_rate'    => $offer['inst_interest_rate'],
            'inst_grace_type'       => $offer['inst_grace_type'],
            'inst_grace_months'     => $offer['inst_grace_months'],
            'inst_post_grace_rate'  => $offer['inst_post_grace_rate'],
            'effective_from'        => $offer['effective_from'],
            'effective_to'          => $offer['effective_to'],
        ];

        if ($tier) {
            $data['tier'] = [
                'id'                => $tier['id'],
                'tier_order'        => $tier['tier_order'],
                'tier_name_ar'      => $tier['tier_name_ar'],
                'payment_type'      => $tier['payment_type'],
                'cash_discount_pct' => $tier['cash_discount_pct'],
                'down_payment_pct'  => $tier['down_payment_pct'],
                'months'            => $tier['months'],
                'interest_rate'     => $tier['interest_rate'],
            ];
        }

        return json_encode($data, JSON_UNESCAPED_UNICODE);
    }

    public static function restoreFromSnapshot(string $json): ?array
    {
        $data = json_decode($json, true);
        if (!is_array($data)) {
            return null;
        }
        return $data;
    }
}
