<?php
declare(strict_types=1);

namespace App\Modules\Pricing\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Pricing\Services\RuleFieldMapper;
use App\Modules\Rules\Services\RuleEngine;

class PricingDashboardController extends Controller
{
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();

        $categories = RuleFieldMapper::getCategoryConfig();
        $grouped = [];

        $today = date('Y-m-d');
        foreach ($categories as $cat => $meta) {
            $rules = $db->select(
                "SELECT * FROM business_rules WHERE category = ? AND is_active = 1 AND branch_id IS NULL AND effective_from <= ? AND (effective_to IS NULL OR effective_to >= ?) ORDER BY rule_code",
                [$cat, $today, $today]
            );
            if (!empty($rules)) {
                $grouped[$cat] = [
                    'meta'  => $meta,
                    'rules' => $rules,
                ];
            }
        }

        $annualRates = $this->getAnnualRates($db);
        $membershipPrices = $this->getMembershipPrices($db);

        return $this->view('Pricing.Views.dashboard', [
            'grouped'          => $grouped,
            'annualRates'      => $annualRates,
            'membershipPrices' => $membershipPrices,
        ]);
    }

    public function saveSection(Request $request, string $category): Response
    {
        $rules = $request->post('rule', []);
        $rawRules = $request->post('rule_raw', []);
        $reason = trim((string) $request->post('change_reason', ''));

        if ($reason === '') {
            $reason = 'تحديث عبر لوحة التسعير';
        }

        $updated = 0;

        foreach ($rules as $ruleCode => $fields) {
            if (!is_array($fields)) {
                continue;
            }
            $currentData = RuleEngine::get($ruleCode);
            if ($currentData === null) {
                continue;
            }

            $newFields = [];
            foreach ($fields as $key => $val) {
                if (is_numeric($val) && strpos($val, '.') !== false) {
                    $newFields[$key] = $val;
                } elseif (is_numeric($val)) {
                    $newFields[$key] = (int) $val;
                } elseif ($val === '0' || $val === '1') {
                    $newFields[$key] = (int) $val;
                } else {
                    $newFields[$key] = $val;
                }
            }

            $currentJson = json_encode($currentData, JSON_UNESCAPED_UNICODE);
            $newJson = json_encode($newFields, JSON_UNESCAPED_UNICODE);

            if ($currentJson !== $newJson) {
                RuleEngine::update($ruleCode, $newJson, $reason);
                $updated++;
            }
        }

        foreach ($rawRules as $ruleCode => $rawJson) {
            $decoded = json_decode($rawJson, true);
            if ($decoded === null) {
                continue;
            }
            $currentData = RuleEngine::get($ruleCode);
            $currentJson = json_encode($currentData, JSON_UNESCAPED_UNICODE);
            $newJson = json_encode($decoded, JSON_UNESCAPED_UNICODE);

            if ($currentJson !== $newJson) {
                RuleEngine::update($ruleCode, $newJson, $reason);
                $updated++;
            }
        }

        if ($request->isAjax()) {
            return $this->json(['success' => true, 'updated' => $updated]);
        }

        return $this->redirect('/pricing')->withSuccess("تم تحديث {$updated} قاعدة بنجاح");
    }

    public function saveAnnualRates(Request $request): Response
    {
        $db = App::getInstance()->db();
        $rates = $request->post('rate', []);
        $reason = trim((string) $request->post('change_reason', 'تحديث الاشتراكات السنوية'));
        $employee = App::getInstance()->currentEmployee();
        $updated = 0;

        foreach ($rates as $id => $amount) {
            $amount = trim((string) $amount);
            if (!is_numeric($amount)) {
                continue;
            }
            $existing = $db->selectOne("SELECT id, base_amount FROM service_catalog WHERE id = ?", [(int) $id]);
            if ($existing && (string) $existing['base_amount'] !== $amount) {
                $db->update('service_catalog', [
                    'base_amount' => $amount,
                    'updated_at'  => date('Y-m-d H:i:s'),
                    'updated_by'  => $employee ? (int) $employee->id : null,
                ], '`id` = ?', [(int) $id]);
                $updated++;
            }
        }

        $devFee = $request->post('dev_fee');
        if ($devFee !== null && is_numeric($devFee)) {
            $currentDev = RuleEngine::get('DEVELOPMENT_FEE');
            if ($currentDev && (string) ($currentDev['amount'] ?? '') !== (string) $devFee) {
                RuleEngine::update('DEVELOPMENT_FEE', json_encode(['amount' => $devFee], JSON_UNESCAPED_UNICODE), $reason);
                $updated++;
            }
        }

        if ($request->isAjax()) {
            return $this->json(['success' => true, 'updated' => $updated]);
        }
        return $this->redirect('/pricing')->withSuccess("تم تحديث {$updated} سعر بنجاح");
    }

    public function addYear(Request $request): Response
    {
        $db = App::getInstance()->db();
        $year = (int) $request->post('year', 0);

        if ($year < 2020 || $year > 2040) {
            return $this->redirect('/pricing')->withError('سنة غير صالحة');
        }

        $fy = "{$year}/" . ($year + 1);
        $effectiveFrom = "{$year}-07-01";
        $effectiveTo = ($year + 1) . "-06-30";

        $exists = $db->selectOne(
            "SELECT id FROM service_catalog WHERE service_code = ? LIMIT 1",
            ["SVC_ANNUAL_MEMBER_{$year}"]
        );
        if ($exists) {
            return $this->redirect('/pricing')->withError("السنة المالية {$fy} موجودة بالفعل");
        }

        $member = (string) $request->post('member_rate', '492');
        $spouse = (string) $request->post('spouse_rate', '492');
        $child = (string) $request->post('child_rate', '222');
        $temp = (string) $request->post('temp_rate', '222');

        $employee = App::getInstance()->currentEmployee();
        $now = date('Y-m-d H:i:s');

        $entries = [
            ["SVC_ANNUAL_MEMBER_{$year}", "اشتراك سنوي - عضو {$year}", $member],
            ["SVC_ANNUAL_SPOUSE_{$year}", "اشتراك سنوي - زوج/ة {$year}", $spouse],
            ["SVC_ANNUAL_CHILD_{$year}", "اشتراك سنوي - ابن/بنت {$year}", $child],
            ["SVC_ANNUAL_TEMP_{$year}", "اشتراك سنوي - مؤقت {$year}", $temp],
        ];

        foreach ($entries as [$code, $name, $amount]) {
            $db->insert('service_catalog', [
                'service_code'  => $code,
                'name_ar'       => $name,
                'price_type'    => 'fixed',
                'base_amount'   => $amount,
                'currency'      => 'EGP',
                'effective_from'=> $effectiveFrom,
                'effective_to'  => $effectiveTo,
                'is_active'     => 1,
                'created_at'    => $now,
                'updated_at'    => $now,
                'created_by'    => $employee ? (int) $employee->id : null,
            ]);
        }

        return $this->redirect('/pricing')->withSuccess("تم إضافة أسعار السنة المالية {$fy} بنجاح");
    }

    public function saveMembershipPrices(Request $request): Response
    {
        $db = App::getInstance()->db();
        $prices = $request->post('price', []);
        $reason = trim((string) $request->post('change_reason', 'تحديث أسعار العضويات'));
        $employee = App::getInstance()->currentEmployee();
        $updated = 0;

        foreach ($prices as $id => $amount) {
            $amount = trim((string) $amount);
            if (!is_numeric($amount)) {
                continue;
            }
            $existing = $db->selectOne("SELECT id, base_amount FROM service_catalog WHERE id = ?", [(int) $id]);
            if ($existing && (string) $existing['base_amount'] !== $amount) {
                $db->update('service_catalog', [
                    'base_amount' => $amount,
                    'updated_at'  => date('Y-m-d H:i:s'),
                    'updated_by'  => $employee ? (int) $employee->id : null,
                ], '`id` = ?', [(int) $id]);
                $updated++;
            }
        }

        if ($request->isAjax()) {
            return $this->json(['success' => true, 'updated' => $updated]);
        }
        return $this->redirect('/pricing')->withSuccess("تم تحديث {$updated} سعر عضوية بنجاح");
    }

    public function ruleVersions(Request $request, string $ruleCode): Response
    {
        $versions = RuleEngine::getVersionHistory($ruleCode);
        return $this->json(['success' => true, 'versions' => $versions]);
    }

    public function addRuleVersion(Request $request, string $ruleCode): Response
    {
        $valueJson = $request->post('value_json', '');
        $effectiveFrom = $request->post('effective_from', '');
        $effectiveTo = $request->post('effective_to', '');
        $reason = trim((string) $request->post('change_reason', 'إضافة نسخة تاريخية'));

        if (!$effectiveFrom || !$effectiveTo) {
            return $this->json(['success' => false, 'error' => 'يجب تحديد تاريخ البداية والنهاية'], 422);
        }
        if ($effectiveTo < $effectiveFrom) {
            return $this->json(['success' => false, 'error' => 'تاريخ النهاية يجب أن يكون بعد تاريخ البداية'], 422);
        }

        $decoded = json_decode($valueJson, true);
        if ($decoded === null && $valueJson !== 'null') {
            return $this->json(['success' => false, 'error' => 'قيمة JSON غير صالحة'], 422);
        }

        try {
            RuleEngine::addHistoricalVersion($ruleCode, $valueJson, $effectiveFrom, $effectiveTo, $reason);
            return $this->json(['success' => true]);
        } catch (\RuntimeException $e) {
            return $this->json(['success' => false, 'error' => $e->getMessage()], 422);
        }
    }

    private function getAnnualRates($db): array
    {
        $rows = $db->select(
            "SELECT * FROM service_catalog WHERE service_code LIKE 'SVC_ANNUAL_%' AND is_active = 1 ORDER BY effective_from DESC, service_code"
        );

        $years = [];
        foreach ($rows as $row) {
            $code = $row['service_code'];
            if (preg_match('/SVC_ANNUAL_(MEMBER|SPOUSE|CHILD|TEMP)_(\d{4})/', $code, $m)) {
                $type = strtolower($m[1]);
                $year = $m[2];
                $years[$year][$type] = $row;
            } elseif (preg_match('/SVC_ANNUAL_(MEMBER|SPOUSE|CHILD|TEMP)$/', $code, $m)) {
                $type = strtolower($m[1]);
                $years['current'][$type] = $row;
            }
        }

        krsort($years);
        return $years;
    }

    private function getMembershipPrices($db): array
    {
        return $db->select(
            "SELECT * FROM service_catalog WHERE service_code LIKE 'SVC_MEMBERSHIP_%' AND is_active = 1 ORDER BY effective_from DESC, service_code"
        );
    }
}
