<?php
declare(strict_types=1);

namespace App\Modules\Seasonal\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Seasonal\Models\SeasonalMembership;
use App\Modules\Seasonal\Services\SeasonalPricingService;
use App\Modules\Cashier\Services\PaymentRequestService;

class SeasonalController extends Controller
{
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();
        $status = $request->get('status', '');

        $where = 's.is_archived = 0';
        $params = [];
        if ($status !== '') {
            $where .= ' AND s.status = ?';
            $params[] = $status;
        }

        $rows = $db->select(
            "SELECT s.*, m.full_name_ar as member_name, m.membership_number, b.name_ar as branch_name
             FROM seasonal_memberships s
             JOIN members m ON m.id = s.member_id
             JOIN branches b ON b.id = s.branch_id
             WHERE {$where}
             ORDER BY s.created_at DESC LIMIT 100",
            $params
        );

        return $this->view('Seasonal.Views.index', ['rows' => $rows, 'status' => $status]);
    }

    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 (($member['membership_type'] ?? 'working') !== 'seasonal') {
            return $this->redirect("/members/{$memberId}")->withError('هذا العضو ليس عضواً موسمياً');
        }

        $existing = $db->selectOne("SELECT id FROM seasonal_memberships WHERE member_id = ? AND person_type = 'member' AND is_archived = 0 LIMIT 1", [(int) $memberId]);
        if ($existing) return $this->redirect("/members/{$memberId}")->withError('بيانات العضوية الموسمية مسجلة بالفعل');

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

        $spouses = $db->select("SELECT id, full_name_ar FROM spouses WHERE member_id = ? AND is_archived = 0 AND status = 'active'", [(int) $memberId]);
        $children = $db->select("SELECT id, full_name_ar, date_of_birth, gender, TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) as age FROM children WHERE member_id = ? AND is_archived = 0", [(int) $memberId]);

        $egyptianPrices = SeasonalPricingService::getPricingTable('egyptian');
        $foreignPrices = SeasonalPricingService::getPricingTable('foreign');

        return $this->view('Seasonal.Views.create', [
            'member'         => $member,
            'branches'       => $branches,
            'qualifications' => $qualifications,
            'spouses'        => $spouses,
            'children'       => $children,
            'egyptianPrices' => $egyptianPrices,
            'foreignPrices'  => $foreignPrices,
        ]);
    }

    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 (($member['membership_type'] ?? 'working') !== 'seasonal') {
            return $this->redirect("/members/{$memberId}")->withError('هذا العضو ليس عضواً موسمياً');
        }

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

        $seasonalNumber = trim((string) ($data['seasonal_number'] ?? ''));
        if ($seasonalNumber === '') {
            return $this->redirect("/members/{$memberId}/seasonal/create")->withError('رقم العضوية الموسمية مطلوب');
        }

        // Check uniqueness of seasonal number
        $existingNumber = $db->selectOne("SELECT id FROM members WHERE membership_number = ? AND id != ?", [$seasonalNumber, (int) $memberId]);
        if ($existingNumber) {
            return $this->redirect("/members/{$memberId}/seasonal/create")->withError('رقم العضوية الموسمية مستخدم بالفعل');
        }

        // Assign the seasonal number to the member immediately
        $db->update('members', [
            'membership_number' => $seasonalNumber,
            'updated_at'        => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $memberId]);

        $nationalityType = in_array($data['nationality_type'] ?? '', ['egyptian', 'foreign'], true)
            ? $data['nationality_type'] : 'egyptian';
        $durationMonths = (int) ($data['duration_months'] ?? 6);
        $branchId = (int) ($data['branch_id'] ?? 0);
        $startDate = $data['start_date'] ?? date('Y-m-d');
        $hasQualification = !empty($data['has_qualification']);

        $validDurations = SeasonalPricingService::getValidDurations($nationalityType);
        if (!in_array($durationMonths, $validDurations, true)) {
            return $this->redirect("/members/{$memberId}/seasonal/create")->withError('مدة غير صالحة');
        }
        if ($branchId <= 0) {
            return $this->redirect("/members/{$memberId}/seasonal/create")->withError('الفرع مطلوب');
        }

        $endDate = date('Y-m-d', strtotime($startDate . " +{$durationMonths} months"));

        // Build items list
        $items = [];
        $memberAge = $member['date_of_birth'] ? (int) ((time() - strtotime($member['date_of_birth'])) / 31557600) : null;

        $items[] = [
            'person_type' => 'member',
            'name'        => $member['full_name_ar'],
            'age'         => $memberAge,
        ];

        // Add selected spouses
        $selectedSpouses = (array) ($data['spouses'] ?? []);
        foreach ($selectedSpouses as $spouseId) {
            $spouse = $db->selectOne("SELECT full_name_ar FROM spouses WHERE id = ? AND member_id = ? AND is_archived = 0", [(int) $spouseId, (int) $memberId]);
            if ($spouse) {
                $items[] = ['person_type' => 'spouse', 'name' => $spouse['full_name_ar'], 'age' => null];
            }
        }

        // Add selected children
        $selectedChildren = (array) ($data['children'] ?? []);
        foreach ($selectedChildren as $childId) {
            $child = $db->selectOne("SELECT full_name_ar, date_of_birth, TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) as age FROM children WHERE id = ? AND member_id = ? AND is_archived = 0", [(int) $childId, (int) $memberId]);
            if ($child) {
                $items[] = ['person_type' => 'child', 'name' => $child['full_name_ar'], 'age' => (int) $child['age']];
            }
        }

        // Add new inline spouses
        $newSpouses = (array) ($data['new_spouses'] ?? []);
        $createdSpouseIds = [];
        foreach ($newSpouses as $ns) {
            $spName = trim($ns['full_name_ar'] ?? '');
            if ($spName === '') continue;
            $spDob = (!empty($ns['date_of_birth']) && strtotime($ns['date_of_birth'])) ? $ns['date_of_birth'] : null;
            $spAgeYears = $spDob ? (int) ((time() - strtotime($spDob)) / 31557600) : null;
            $spAgeMonths = $spDob ? (int) (((time() - strtotime($spDob)) % 31557600) / 2629800) : null;
            $sp = \App\Modules\Spouses\Models\Spouse::create([
                'member_id'        => (int) $memberId,
                'full_name_ar'     => $spName,
                'full_name_en'     => trim($ns['full_name_en'] ?? '') ?: null,
                'national_id'      => trim($ns['national_id'] ?? '') ?: null,
                'passport_number'  => trim($ns['passport_number'] ?? '') ?: null,
                'date_of_birth'    => $spDob,
                'age_years'        => $spAgeYears,
                'age_months'       => $spAgeMonths,
                'gender'           => $ns['gender'] ?? 'female',
                'nationality'      => $ns['nationality'] ?? 'egyptian',
                'marriage_date'    => (!empty($ns['marriage_date']) && strtotime($ns['marriage_date'])) ? $ns['marriage_date'] : null,
                'qualification_id' => !empty($ns['qualification_id']) ? (int) $ns['qualification_id'] : null,
                'occupation'       => trim($ns['occupation'] ?? '') ?: null,
                'mobile'           => trim($ns['mobile'] ?? '') ?: null,
                'work_phone'       => trim($ns['work_phone'] ?? '') ?: null,
                'work_address'     => trim($ns['work_address'] ?? '') ?: null,
                'spouse_order'     => \App\Modules\Spouses\Models\Spouse::countActiveForMember((int) $memberId) + 1,
                'status'           => 'active',
                'join_date'        => date('Y-m-d'),
            ]);
            $createdSpouseIds[] = (int) $sp->id;
            $items[] = ['person_type' => 'spouse', 'name' => $spName, 'age' => null];
        }

        // Add new inline children
        $newChildren = (array) ($data['new_children'] ?? []);
        $createdChildIds = [];
        foreach ($newChildren as $nc) {
            $chName = trim($nc['full_name_ar'] ?? '');
            $chDob = (!empty($nc['date_of_birth']) && strtotime($nc['date_of_birth'])) ? $nc['date_of_birth'] : '';
            if ($chName === '' || $chDob === '') continue;
            $childAge = (int) ((time() - strtotime($chDob)) / 31557600);
            $childMonths = (int) (((time() - strtotime($chDob)) % 31557600) / 2629800);
            $chGender = in_array($nc['gender'] ?? '', ['male', 'female'], true) ? $nc['gender'] : 'male';
            $chRelation = in_array($nc['relationship'] ?? '', ['son', 'daughter'], true) ? $nc['relationship'] : ($chGender === 'female' ? 'daughter' : 'son');
            $ch = \App\Modules\Children\Models\Child::create([
                'member_id'               => (int) $memberId,
                'child_order'             => \App\Modules\Children\Models\Child::countActiveForMember((int) $memberId) + 1,
                'full_name_ar'            => $chName,
                'full_name_en'            => trim($nc['full_name_en'] ?? '') ?: null,
                'national_id'             => trim($nc['national_id'] ?? '') ?: null,
                'passport_number'         => trim($nc['passport_number'] ?? '') ?: null,
                'birth_certificate_number' => trim($nc['birth_certificate_number'] ?? '') ?: null,
                'date_of_birth'           => $chDob,
                'age_years'               => $childAge,
                'age_months'              => $childMonths,
                'gender'                  => $chGender,
                'relationship'            => $chRelation,
                'nationality'             => $nc['nationality'] ?? 'egyptian',
                'school_faculty'          => trim($nc['school_faculty'] ?? '') ?: null,
                'classification'          => 'included',
                'status'                  => 'active',
                'join_date'               => date('Y-m-d'),
            ]);
            $createdChildIds[] = (int) $ch->id;
            $items[] = ['person_type' => 'child', 'name' => $chName, 'age' => $childAge];
        }

        // Add new inline temporary members
        $newTemps = (array) ($data['new_temps'] ?? []);
        $createdTempIds = [];
        foreach ($newTemps as $nt) {
            $tName = trim($nt['full_name_ar'] ?? '');
            if ($tName === '') continue;
            $tDob = (!empty($nt['date_of_birth']) && strtotime($nt['date_of_birth'])) ? $nt['date_of_birth'] : null;
            $tAgeYears = $tDob ? (int) ((time() - strtotime($tDob)) / 31557600) : null;
            $tAgeMonths = $tDob ? (int) (((time() - strtotime($tDob)) % 31557600) / 2629800) : null;
            $tGender = in_array($nt['gender'] ?? '', ['male', 'female'], true) ? $nt['gender'] : 'male';
            $tm = \App\Modules\Temporary\Models\TemporaryMember::create([
                'member_id'              => (int) $memberId,
                'full_name_ar'           => $tName,
                'full_name_en'           => trim($nt['full_name_en'] ?? '') ?: null,
                'category'               => $nt['category'] ?? 'relative',
                'national_id'            => trim($nt['national_id'] ?? '') ?: null,
                'passport_number'        => trim($nt['passport_number'] ?? '') ?: null,
                'date_of_birth'          => $tDob,
                'age_years'              => $tAgeYears,
                'age_months'             => $tAgeMonths,
                'gender'                 => $tGender,
                'nationality'            => $nt['nationality'] ?? 'egyptian',
                'relationship_to_member' => trim($nt['relationship_to_member'] ?? '') ?: null,
                'has_championship'       => !empty($nt['has_championship']) ? 1 : 0,
                'disability_documentation' => !empty($nt['disability_documentation']) ? 1 : 0,
                'notes'                  => trim($nt['notes'] ?? '') ?: null,
                'status'                 => 'active',
                'join_date'              => date('Y-m-d'),
            ]);
            $createdTempIds[] = (int) $tm->id;
            $tAge = $tDob ? $tAgeYears : null;
            $items[] = ['person_type' => 'child', 'name' => $tName, 'age' => $tAge ?? 20];
        }

        // Calculate pricing
        $pricing = SeasonalPricingService::calculate($items, $nationalityType, $durationMonths, $hasQualification);

        // Create parent seasonal membership
        $parentSeasonal = SeasonalMembership::create([
            'member_id'        => (int) $memberId,
            'branch_id'        => $branchId,
            'nationality_type' => $nationalityType,
            'duration_months'  => $durationMonths,
            'person_type'      => 'member',
            'person_name'      => $member['full_name_ar'],
            'person_age'       => $memberAge,
            'age_category'     => ($memberAge && $memberAge >= 60) ? 'over_60' : null,
            'start_date'       => $startDate,
            'end_date'         => $endDate,
            'fee_amount'       => $pricing['items'][0]['base_price'],
            'currency'         => $pricing['currency'],
            'vat_amount'       => $pricing['vat_amount'],
            'discount_amount'  => $pricing['total_discount'],
            'discount_type'    => $pricing['family_discount']['type'] ?? ($hasQualification ? null : 'no_qualification'),
            'total_amount'     => $pricing['grand_total'],
            'status'           => 'pending_payment',
            'carnet_marking'   => 'موسمي',
            'includes_pool'    => 1,
            'notes'            => $data['notes'] ?? null,
        ]);

        $parentId = (int) $parentSeasonal->id;

        // Create child records for family members
        for ($i = 1; $i < count($items); $i++) {
            $item = $items[$i];
            $lineItem = $pricing['items'][$i];

            SeasonalMembership::create([
                'member_id'          => (int) $memberId,
                'parent_seasonal_id' => $parentId,
                'branch_id'          => $branchId,
                'nationality_type'   => $nationalityType,
                'duration_months'    => $durationMonths,
                'person_type'        => $item['person_type'],
                'person_name'        => $item['name'],
                'person_age'         => $item['age'],
                'age_category'       => $lineItem['age_category'],
                'start_date'         => $startDate,
                'end_date'           => $endDate,
                'fee_amount'         => $lineItem['base_price'],
                'currency'           => $pricing['currency'],
                'vat_amount'         => '0.00',
                'discount_amount'    => '0.00',
                'total_amount'       => $lineItem['base_price'],
                'status'             => 'pending_payment',
                'carnet_marking'     => 'موسمي',
                'includes_pool'      => 1,
            ]);
        }

        // Send collective payment request
        $breakdown = [];
        foreach ($pricing['items'] as $li) {
            $catLabel = SeasonalPricingService::getCategoryLabel($li['age_category'] ?? $li['person_type']);
            $breakdown[] = '📌 ' . $li['person_name'] . ' (' . $catLabel . '): ' . $li['base_price'] . ' ' . $pricing['currency'];
        }
        $breakdown[] = '═══════════════════════════';
        $breakdown[] = '💰 المجموع قبل الخصم: ' . $pricing['subtotal'] . ' ' . $pricing['currency'];
        if (bccomp($pricing['total_discount'], '0', 2) > 0) {
            $discLabel = $pricing['family_discount']['label'] ?? 'خصم عدم وجود مؤهل عالي';
            $breakdown[] = '🏷️ ' . $discLabel . ': -' . $pricing['total_discount'] . ' ' . $pricing['currency'];
        }
        $breakdown[] = '📊 ضريبة القيمة المضافة (' . $pricing['vat_rate'] . '%): ' . $pricing['vat_amount'] . ' ' . $pricing['currency'];
        $breakdown[] = '💵 الإجمالي: ' . $pricing['grand_total'] . ' ' . $pricing['currency'];

        $payResult = PaymentRequestService::createRequest([
            'member_id'           => (int) $memberId,
            'amount'              => $pricing['grand_total'],
            'payment_type'        => 'seasonal_fee',
            'related_entity_type' => 'seasonal_memberships',
            'related_entity_id'   => $parentId,
            'description_ar'      => 'عضوية موسمية ' . ($nationalityType === 'foreign' ? '(أجنبي)' : '(مصري)') . ' — ' . $durationMonths . ' شهر — من ' . $startDate,
            'notes'               => json_encode(['fee_breakdown' => $breakdown], JSON_UNESCAPED_UNICODE),
        ]);

        EventBus::dispatch('seasonal.created', [
            'member_id'        => (int) $memberId,
            'seasonal_id'      => $parentId,
            'nationality_type' => $nationalityType,
            'duration_months'  => $durationMonths,
            'total'            => $pricing['grand_total'],
            'currency'         => $pricing['currency'],
            'items_count'      => count($items),
        ]);

        $msg = 'تم إنشاء العضوية الموسمية (' . count($items) . ' فرد) — الإجمالي: ' . $pricing['grand_total'] . ' ' . $pricing['currency'];
        if ($payResult['success']) {
            $msg .= ' — طلب الخزينة: ' . $payResult['request_number'];
        }

        return $this->redirect("/members/{$memberId}")->withSuccess($msg);
    }

    public function pricePreview(Request $request): Response
    {
        $nationalityType = $request->get('nationality_type', 'egyptian');
        $durationMonths = (int) $request->get('duration_months', 6);
        $memberId = (int) $request->get('member_id', 0);
        $hasQualification = (bool) $request->get('has_qualification', 1);
        $selectedSpouses = explode(',', $request->get('spouses', ''));
        $selectedChildren = explode(',', $request->get('children', ''));

        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT full_name_ar, date_of_birth FROM members WHERE id = ? AND is_archived = 0", [$memberId]);
        if (!$member) return $this->json(['error' => 'member not found']);

        $memberAge = $member['date_of_birth'] ? (int) ((time() - strtotime($member['date_of_birth'])) / 31557600) : null;
        $items = [['person_type' => 'member', 'name' => $member['full_name_ar'], 'age' => $memberAge]];

        foreach (array_filter($selectedSpouses) as $sid) {
            $sp = $db->selectOne("SELECT full_name_ar FROM spouses WHERE id = ? AND member_id = ? AND is_archived = 0", [(int) $sid, $memberId]);
            if ($sp) $items[] = ['person_type' => 'spouse', 'name' => $sp['full_name_ar'], 'age' => null];
        }
        foreach (array_filter($selectedChildren) as $cid) {
            $ch = $db->selectOne("SELECT full_name_ar, TIMESTAMPDIFF(YEAR, date_of_birth, CURDATE()) as age FROM children WHERE id = ? AND member_id = ? AND is_archived = 0", [(int) $cid, $memberId]);
            if ($ch) $items[] = ['person_type' => 'child', 'name' => $ch['full_name_ar'], 'age' => (int) $ch['age']];
        }

        // New inline spouses
        $newSpousesCount = (int) $request->get('new_spouses_count', 0);
        for ($i = 0; $i < $newSpousesCount; $i++) {
            $items[] = ['person_type' => 'spouse', 'name' => 'زوجة جديدة', 'age' => null];
        }

        // New inline children (with DOBs for age calculation)
        $newChildDobs = array_filter(explode(',', $request->get('new_children_dobs', '')));
        foreach ($newChildDobs as $dob) {
            $dob = trim($dob);
            if ($dob && strtotime($dob)) {
                $childAge = (int) ((time() - strtotime($dob)) / 31557600);
                $items[] = ['person_type' => 'child', 'name' => 'ابن/ة جديد/ة', 'age' => $childAge];
            }
        }

        $pricing = SeasonalPricingService::calculate($items, $nationalityType, $durationMonths, $hasQualification);

        return $this->json($pricing);
    }
}
