<?php
declare(strict_types=1);

namespace App\Modules\Accounting\Services;

use App\Core\App;

final class MultiCurrencyService
{
    public static function getBaseCurrency(): array
    {
        $db = App::getInstance()->db();
        $currency = $db->selectOne("SELECT * FROM currencies WHERE is_base_currency = 1 LIMIT 1");
        return $currency ?: ['code' => 'EGP', 'name_ar' => 'جنيه مصري', 'symbol' => 'ج.م', 'decimal_places' => 2];
    }

    public static function getExchangeRate(string $currencyCode, ?string $date = null): array
    {
        if ($currencyCode === 'EGP') {
            return ['buy_rate' => '1.000000', 'sell_rate' => '1.000000', 'mid_rate' => '1.000000'];
        }

        $db = App::getInstance()->db();
        $date = $date ?? date('Y-m-d');

        $currency = $db->selectOne("SELECT id FROM currencies WHERE code = ?", [$currencyCode]);
        if (!$currency) {
            return ['buy_rate' => '1.000000', 'sell_rate' => '1.000000', 'mid_rate' => '1.000000'];
        }

        $rate = $db->selectOne(
            "SELECT * FROM exchange_rates WHERE currency_id = ? AND rate_date <= ? ORDER BY rate_date DESC LIMIT 1",
            [(int) $currency['id'], $date]
        );

        if (!$rate) {
            return ['buy_rate' => '1.000000', 'sell_rate' => '1.000000', 'mid_rate' => '1.000000'];
        }

        return [
            'buy_rate' => (string) $rate['buy_rate'],
            'sell_rate' => (string) $rate['sell_rate'],
            'mid_rate' => (string) $rate['mid_rate'],
        ];
    }

    public static function convert(string $amount, string $fromCurrency, string $toCurrency, ?string $date = null): array
    {
        if ($fromCurrency === $toCurrency) {
            return ['converted_amount' => $amount, 'rate' => '1.000000'];
        }

        $baseCurrency = self::getBaseCurrency()['code'];

        if ($fromCurrency === $baseCurrency) {
            $rate = self::getExchangeRate($toCurrency, $date);
            $converted = bcdiv($amount, $rate['mid_rate'], 2);
            return ['converted_amount' => $converted, 'rate' => $rate['mid_rate']];
        }

        if ($toCurrency === $baseCurrency) {
            $rate = self::getExchangeRate($fromCurrency, $date);
            $converted = bcmul($amount, $rate['mid_rate'], 2);
            return ['converted_amount' => $converted, 'rate' => $rate['mid_rate']];
        }

        $fromRate = self::getExchangeRate($fromCurrency, $date);
        $toRate = self::getExchangeRate($toCurrency, $date);
        $baseAmount = bcmul($amount, $fromRate['mid_rate'], 6);
        $converted = bcdiv($baseAmount, $toRate['mid_rate'], 2);
        $crossRate = bcdiv($fromRate['mid_rate'], $toRate['mid_rate'], 6);

        return ['converted_amount' => $converted, 'rate' => $crossRate];
    }

    public static function calculateGainLoss(string $originalAmount, string $originalRate, string $currentRate, string $currency): array
    {
        $originalBase = bcmul($originalAmount, $originalRate, 2);
        $currentBase = bcmul($originalAmount, $currentRate, 2);
        $difference = bcsub($currentBase, $originalBase, 2);

        return [
            'original_base_amount' => $originalBase,
            'current_base_amount' => $currentBase,
            'gain_loss' => $difference,
            'is_gain' => bccomp($difference, '0', 2) > 0,
        ];
    }

    public static function getActiveCurrencies(): array
    {
        $db = App::getInstance()->db();
        return $db->select("SELECT * FROM currencies WHERE is_active = 1 ORDER BY is_base_currency DESC, name_ar ASC");
    }

    public static function setExchangeRate(string $currencyCode, string $buyRate, string $sellRate, ?string $date = null): bool
    {
        $db = App::getInstance()->db();
        $date = $date ?? date('Y-m-d');

        $currency = $db->selectOne("SELECT id FROM currencies WHERE code = ?", [$currencyCode]);
        if (!$currency) return false;

        $midRate = bcdiv(bcadd($buyRate, $sellRate, 6), '2', 6);

        $existing = $db->selectOne(
            "SELECT id FROM exchange_rates WHERE currency_id = ? AND rate_date = ?",
            [(int) $currency['id'], $date]
        );

        if ($existing) {
            $db->update('exchange_rates', [
                'buy_rate' => $buyRate,
                'sell_rate' => $sellRate,
                'mid_rate' => $midRate,
            ], 'id = ?', [(int) $existing['id']]);
        } else {
            $db->insert('exchange_rates', [
                'currency_id' => (int) $currency['id'],
                'rate_date' => $date,
                'buy_rate' => $buyRate,
                'sell_rate' => $sellRate,
                'mid_rate' => $midRate,
            ]);
        }

        return true;
    }
}
