<?php
declare(strict_types=1);

namespace App\Modules\Spouses\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Spouses\Models\Spouse;
use App\Modules\Spouses\Services\SpouseFeeCalculator;
use App\Modules\Members\Services\NationalIdParser;
use App\Modules\Rules\Services\RuleEngine;
use App\Modules\Cashier\Services\PaymentRequestService;
use App\Shared\Services\PhotoUploadService;
use App\Modules\Members\Services\MembershipRulesService;


class SpouseController extends Controller
{
    private static function isSuperAdmin(): bool
    {
        $employee = App::getInstance()->currentEmployee();
        if (!$employee) return false;
        $db = App::getInstance()->db();
        $row = $db->selectOne(
            "SELECT 1 FROM employee_roles er JOIN roles r ON r.id = er.role_id WHERE er.employee_id = ? AND r.role_code = 'super_admin' AND er.is_active = 1 LIMIT 1",
            [(int) $employee->id]
        );
        return $row !== null;
    }

    private static function isLocked(array $member): bool
    {
        return !empty($member['membership_number']);
    }

    public function create(Request $request, string $memberId): Response
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ? AND is_archived = 0", [(int) $memberId]);
        if (!$member) {
            return $this->redirect('/members')->withError('العضو غير موجود');
        }

        if (!MembershipRulesService::allowsDependents($member['membership_type'] ?? 'working')) {
            return $this->redirect("/members/{$memberId}")->withError('نوع العضوية لا يسمح بإضافة تابعين');
        }

        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن إضافة زوج/ة بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        $currentCount = Spouse::countActiveForMember((int) $memberId);
        $maxAllowed = Spouse::getMaxSpouses($member['gender']);

        if ($currentCount >= $maxAllowed) {
            $msg = $member['gender'] === 'female'
                ? 'العضوة لديها زوج مسجل بالفعل — لا يمكن إضافة أكثر من زوج واحد'
                : 'تم الوصول للحد الأقصى من الزوجات (' . $maxAllowed . ')';
            return $this->redirect("/members/{$memberId}")->withError($msg);
        }

        $qualifications = $db->select("SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order");
        $countries = $db->select("SELECT id, nationality_ar FROM countries WHERE is_active = 1 ORDER BY nationality_ar");

        return $this->view('Spouses.Views.create', [
            'member'         => $member,
            'spouseOrder'    => $currentCount + 1,
            'qualifications' => $qualifications,
            'countries'      => $countries,
            'requiredGender' => Spouse::getRequiredSpouseGender($member['gender']),
            'maxAllowed'     => $maxAllowed,
            'currentCount'   => $currentCount,
        ]);
    }

    public function store(Request $request, string $memberId): Response
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ? AND is_archived = 0", [(int) $memberId]);
        if (!$member) {
            return $this->redirect('/members')->withError('العضو غير موجود');
        }

        if (!MembershipRulesService::allowsDependents($member['membership_type'] ?? 'working')) {
            return $this->redirect("/members/{$memberId}")->withError('نوع العضوية لا يسمح بإضافة تابعين');
        }

        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن إضافة زوج/ة بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        $data = $request->all();
        unset($data['_csrf_token']);

        $errors = [];

        if (empty(trim($data['full_name_ar'] ?? ''))) $errors[] = 'اسم الزوج/الزوجة مطلوب';
        if (empty($data['date_of_birth'] ?? '')) $errors[] = 'تاريخ الميلاد مطلوب';
        if (empty($data['gender'] ?? '')) $errors[] = 'النوع مطلوب';
        elseif (!in_array($data['gender'], ['male', 'female'], true)) $errors[] = 'النوع يجب أن يكون ذكر أو أنثى';
        if (empty($data['marriage_date'] ?? '')) $errors[] = 'تاريخ الزواج مطلوب';

        // ── Gender & count validation ──
        $requiredGender = Spouse::getRequiredSpouseGender($member['gender']);
        $maxAllowed = Spouse::getMaxSpouses($member['gender']);
        $currentCount = Spouse::countActiveForMember((int) $memberId);

        if ($currentCount >= $maxAllowed) {
            $errors[] = $member['gender'] === 'female'
                ? 'العضوة لديها زوج مسجل بالفعل — لا يمكن إضافة أكثر من زوج واحد'
                : 'تم الوصول للحد الأقصى من الزوجات (' . $maxAllowed . ')';
        }

        if (!empty($data['gender']) && $data['gender'] !== $requiredGender) {
            $errors[] = $member['gender'] === 'female'
                ? 'يجب أن يكون الزوج ذكراً'
                : 'يجب أن تكون الزوجة أنثى';
        }

        // Force the correct gender regardless of what was submitted
        $data['gender'] = $requiredGender;

        // ── NID parsing ──
        $nid = trim($data['national_id'] ?? '');
        if ($nid !== '') {
            $parsed = NationalIdParser::parse($nid);
            if (!$parsed['is_valid']) {
                $errors = array_merge($errors, $parsed['errors']);
            } else {
                $data['date_of_birth'] = $parsed['dob'];
                $data['age_years'] = $parsed['age_years'];
                $data['age_months'] = $parsed['age_months'];

                // Validate NID gender matches required gender
                if ($parsed['gender'] !== $requiredGender) {
                    $genderLabel = $requiredGender === 'male' ? 'ذكر' : 'أنثى';
                    $errors[] = "الرقم القومي يشير إلى نوع مختلف — المطلوب: {$genderLabel}";
                }

                $data['gender'] = $parsed['gender'];
            }

            if ($nid === ($member['national_id'] ?? '')) {
                $errors[] = 'لا يمكن إضافة العضو نفسه كزوج/زوجة';
            }

            $dup = Spouse::nidExistsElsewhere($nid);
            if ($dup) {
                $errors[] = 'الرقم القومي مسجل بالفعل: ' . ($dup['data']['full_name_ar'] ?? '');
            }
        }

        // ── Age calculation ──
        if (!empty($data['date_of_birth']) && empty($data['age_years'])) {
            $age = age_from_dob($data['date_of_birth']);
            $data['age_years'] = $age['years'];
            $data['age_months'] = $age['months'];
        }

        $spouseMinAge = (int) (RuleEngine::getValue('SPOUSE_MIN_AGE', 'value') ?? 18);
        if ((int) ($data['age_years'] ?? 0) < $spouseMinAge) {
            $errors[] = 'الحد الأدنى للسن ' . $spouseMinAge . ' سنة';
        }

        $photoFile = $_FILES['photo'] ?? [];
        if (!PhotoUploadService::isUploaded($photoFile)) {
            $errors[] = 'الصورة الشخصية مطلوبة';
        } else {
            $photoValidation = PhotoUploadService::validate($photoFile);
            if (!$photoValidation['valid']) {
                $errors = array_merge($errors, $photoValidation['errors']);
            }
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $data);
            return $this->redirect("/members/{$memberId}/spouses/create");
        }

        // ── Fee calculation — pass spouse data array ──
        $feeCalc = SpouseFeeCalculator::calculate((int) $memberId, [
            'nationality'   => $data['nationality'] ?? 'مصري',
            'marriage_date' => $data['marriage_date'] ?? null,
        ]);

        if (!empty($feeCalc['error'])) {
            return $this->redirect("/members/{$memberId}/spouses/create")->withError($feeCalc['error']);
        }

        $spouseOrder = $feeCalc['spouse_order'] ?? ($currentCount + 1);

        $totalFee = $feeCalc['total_fee'] ?? '0.00';
        $hasFee = bccomp($totalFee, '0', 2) > 0;
        $pendingCalc = !empty($feeCalc['pending_calculation']);

        $breakdownJson = !empty($feeCalc['breakdown']) ? json_encode($feeCalc['breakdown'], JSON_UNESCAPED_UNICODE) : null;

        $spouse = Spouse::create([
            'member_id'          => (int) $memberId,
            'spouse_order'       => $spouseOrder,
            'full_name_ar'       => trim($data['full_name_ar']),
            'full_name_en'       => trim($data['full_name_en'] ?? ''),
            'national_id'        => $nid ?: null,
            'passport_number'    => $data['passport_number'] ?? null,
            'date_of_birth'      => $data['date_of_birth'],
            'age_years'          => (int) ($data['age_years'] ?? 0),
            'age_months'         => (int) ($data['age_months'] ?? 0),
            'gender'             => $data['gender'],
            'nationality'        => $data['nationality'] ?? 'مصري',
            'religion'           => $data['religion'] ?? null,
            'qualification_id'   => !empty($data['qualification_id']) ? (int) $data['qualification_id'] : null,
            'occupation'         => $data['occupation'] ?? null,
            'work_address'       => $data['work_address'] ?? null,
            'work_phone'         => $data['work_phone'] ?? null,
            'mobile'             => $data['mobile'] ?? null,
            'marriage_date'      => $data['marriage_date'],
            'join_date'          => date('Y-m-d'),
            'classification'     => ((int) ($data['age_years'] ?? 0) >= 21) ? 'working' : 'dependent',
            'addition_fee'       => $totalFee,
            'fee_breakdown_json' => $breakdownJson,
            'status'             => ($hasFee || $pendingCalc) ? 'pending_payment' : 'active',
        ]);

        $photoResult = PhotoUploadService::upload($photoFile, 'spouses', (int) $spouse->id);
        if ($photoResult) {
            $spouse->update(['photo_path' => $photoResult['path']]);
        }

        EventBus::dispatch('spouse.added', [
            'member_id'   => (int) $memberId,
            'spouse_id'   => (int) $spouse->id,
            'spouse_order'=> $spouseOrder,
            'fee'         => $totalFee,
        ]);

        $genderWord = $requiredGender === 'male' ? 'الزوج' : 'الزوجة';

        if ($hasFee && !empty($member['membership_number'])) {
            $breakdown = $feeCalc['breakdown'] ?? [];
            PaymentRequestService::createRequest([
                'member_id'           => (int) $memberId,
                'amount'              => $totalFee,
                'payment_type'        => 'addition_fee',
                'related_entity_type' => 'spouses',
                'related_entity_id'   => (int) $spouse->id,
                'description_ar'      => 'رسوم إضافة ' . $genderWord . ' — ' . trim($data['full_name_ar']),
                'notes'               => json_encode(['fee_breakdown' => $breakdown], JSON_UNESCAPED_UNICODE),
            ]);
            return $this->redirect("/members/{$memberId}")
                ->withSuccess("تم إضافة {$genderWord} — الرسوم: " . money($totalFee) . ' — تم إرسالها للخزينة تلقائياً');
        }

        if ($hasFee) {
            return $this->redirect("/members/{$memberId}")
                ->withSuccess("تم إضافة {$genderWord} — الرسوم: " . money($totalFee) . ' — سيتم تحصيلها ضمن الفاتورة المجمعة');
        }

        return $this->redirect("/members/{$memberId}")
            ->withSuccess("تم إضافة {$genderWord} — الترتيب: #{$spouseOrder} — مشمول/ة في قيمة العضوية");
    }

    public function show(Request $request, string $memberId, string $id): Response
    {
        $spouse = Spouse::find((int) $id);
        if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
            return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج/الزوجة غير موجودة');
        }

        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);

        return $this->view('Spouses.Views.show', ['member' => $member, 'spouse' => $spouse]);
    }

    public function edit(Request $request, string $memberId, string $id): Response
    {
        $spouse = Spouse::find((int) $id);
        if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
            return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج/الزوجة غير موجودة');
        }

        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);

        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن تعديل البيانات بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        $qualifications = $db->select("SELECT id, name_ar FROM qualifications WHERE is_active = 1 ORDER BY sort_order");

        return $this->view('Spouses.Views.edit', [
            'member'         => $member,
            'spouse'         => $spouse,
            'qualifications' => $qualifications,
        ]);
    }

    public function update(Request $request, string $memberId, string $id): Response
    {
        $spouse = Spouse::find((int) $id);
        if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
            return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج/الزوجة غير موجودة');
        }

        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);
        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن تعديل البيانات بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        $data = $request->all();
        unset($data['_csrf_token']);

        $updateData = [];
        foreach (['full_name_en', 'occupation', 'work_address', 'work_phone', 'mobile', 'religion'] as $field) {
            if (array_key_exists($field, $data)) {
                $val = $data[$field];
                $updateData[$field] = ($val === '' || $val === null) ? null : $val;
            }
        }
        if (!empty($data['qualification_id'])) {
            $updateData['qualification_id'] = (int) $data['qualification_id'];
        }

        if (!empty($_FILES['photo']) && PhotoUploadService::isUploaded($_FILES['photo'])) {
            $photoValidation = PhotoUploadService::validate($_FILES['photo']);
            if ($photoValidation['valid']) {
                $photoResult = PhotoUploadService::upload($_FILES['photo'], 'spouses', (int) $id);
                if ($photoResult) {
                    $updateData['photo_path'] = $photoResult['path'];
                }
            }
        }

        if (!empty($updateData)) {
            $spouse->update($updateData);
        }

        return $this->redirect("/members/{$memberId}")->withSuccess('تم تحديث بيانات الزوج/الزوجة');
    }

    public function archive(Request $request, string $memberId, string $id): Response
    {
        $spouse = Spouse::find((int) $id);
        if (!$spouse || (int) $spouse->member_id !== (int) $memberId) {
            return $this->redirect("/members/{$memberId}")->withError('بيانات الزوج/الزوجة غير موجودة');
        }

        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);
        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن إزالة التابعين بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        $reason = trim((string) $request->post('reason', ''));
        if ($reason === '') {
            return $this->redirect("/members/{$memberId}")->withError('يجب إدخال سبب الإزالة');
        }

        $employee = App::getInstance()->currentEmployee();
        $db = App::getInstance()->db();

        $db->update('spouses', [
            'is_archived' => 1,
            'archived_at' => date('Y-m-d H:i:s'),
            'archived_by' => $employee ? (int) $employee->id : null,
            'status'      => 'inactive',
            'updated_at'  => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        EventBus::dispatch('spouse.removed', [
            'member_id' => (int) $memberId,
            'spouse_id' => (int) $id,
            'reason'    => $reason,
        ]);

        return $this->redirect("/members/{$memberId}")->withSuccess('تم إزالة الزوج/الزوجة');
    }
}