<?php
declare(strict_types=1);

namespace App\Modules\Temporary\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Temporary\Models\TemporaryMember;
use App\Modules\Temporary\Services\TemporaryFeeCalculator;
use App\Modules\Members\Services\NationalIdParser;
use App\Modules\Cashier\Services\PaymentRequestService;

class TemporaryController extends Controller
{
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();
        $filters = [
            'category'  => $request->get('category', ''),
            'status'    => $request->get('status', ''),
            'q'         => trim((string) $request->get('q', '')),
        ];

        $where = 't.is_archived = 0';
        $params = [];

        if (!empty($filters['category'])) {
            $where .= ' AND t.category = ?';
            $params[] = $filters['category'];
        }
        if (!empty($filters['status'])) {
            $where .= ' AND t.status = ?';
            $params[] = $filters['status'];
        }
        if (!empty($filters['q'])) {
            $where .= ' AND (t.full_name_ar LIKE ? OR t.national_id LIKE ? OR m.full_name_ar LIKE ?)';
            $s = '%' . $filters['q'] . '%';
            $params = array_merge($params, [$s, $s, $s]);
        }

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

        return $this->view('Temporary.Views.index', [
            'rows'       => $rows,
            'filters'    => $filters,
            'categories' => TemporaryMember::getCategories(),
        ]);
    }

    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('العضو غير موجود');
        }

        return $this->view('Temporary.Views.create', [
            'member'     => $member,
            'categories' => TemporaryMember::getCategories(),
        ]);
    }

    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('العضو غير موجود');
        }

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

        $errors = [];
        if (empty(trim($data['full_name_ar'] ?? ''))) $errors[] = 'الاسم مطلوب';
        if (empty($data['category'] ?? '')) $errors[] = 'الفئة مطلوبة';
        if (empty($data['date_of_birth'] ?? '')) $errors[] = 'تاريخ الميلاد مطلوب';
        if (empty($data['gender'] ?? '')) $errors[] = 'النوع مطلوب';

        $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'];
                $data['gender'] = $parsed['gender'];
            }

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

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

        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'];
        }

        $category = $data['category'] ?? '';
        $catErrors = TemporaryFeeCalculator::validateCategory($category, $data, $member);
        $errors = array_merge($errors, $catErrors);

        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}/temporary/create");
        }

        $feeCalc = TemporaryFeeCalculator::calculate((int) $memberId, $data);

        $totalFee = $feeCalc['total_fee'] ?? $feeCalc['fee'] ?? '0.00';
        $hasFee = bccomp($totalFee, '0', 2) > 0;

        $temp = TemporaryMember::create([
            'member_id'                => (int) $memberId,
            'category'                 => $category,
            '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'] ?? 'مصري',
            'relationship_to_member'   => $data['relationship_to_member'] ?? null,
            'has_championship'         => !empty($data['has_championship']) ? 1 : 0,
            'disability_documentation' => !empty($data['disability_documentation']) ? 1 : 0,
            'addition_fee'             => $totalFee,
            'can_separate'             => TemporaryFeeCalculator::canSeparate($category) ? 1 : 0,
            'can_get_independent'      => TemporaryFeeCalculator::canGetIndependent($category) ? 1 : 0,
            'status'                   => $hasFee ? 'pending_payment' : 'active',
            'notes'                    => $data['notes'] ?? null,
        ]);

        EventBus::dispatch('temporary.added', [
            'member_id'    => (int) $memberId,
            'temporary_id' => (int) $temp->id,
            'category'     => $category,
            'fee'          => $totalFee,
        ]);

        if ($hasFee) {
            $catLabel = $temp->getCategoryLabel();
            $payResult = PaymentRequestService::createRequest([
                'member_id'           => (int) $memberId,
                'amount'              => $totalFee,
                'payment_type'        => 'addition_fee',
                'related_entity_type' => 'temporary_members',
                'related_entity_id'   => (int) $temp->id,
                'description_ar'      => 'رسوم إضافة عضو مؤقت (' . $catLabel . ') — ' . trim($data['full_name_ar']),
                'notes'               => json_encode(['fee_breakdown' => $feeCalc['breakdown'] ?? []], JSON_UNESCAPED_UNICODE),
            ]);

            if ($payResult['success']) {
                return $this->redirect("/members/{$memberId}")
                    ->withSuccess('تم إضافة العضو المؤقت وإرسال طلب الدفع للخزينة — الرسوم: ' . money($totalFee) . ' — رقم الطلب: ' . $payResult['request_number']);
            }

            return $this->redirect("/members/{$memberId}")
                ->withError('تم إضافة العضو المؤقت لكن فشل إنشاء طلب الدفع: ' . ($payResult['error'] ?? ''));
        }

        return $this->redirect("/members/{$memberId}")
            ->withSuccess('تم إضافة العضو المؤقت — معفى من الرسوم');
    }

    public function show(Request $request, string $memberId, string $id): Response
    {
        $temp = TemporaryMember::find((int) $id);
        if (!$temp || (int) $temp->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('Temporary.Views.show', ['member' => $member, 'temp' => $temp]);
    }

    public function archive(Request $request, string $memberId, string $id): Response
    {
        $temp = TemporaryMember::find((int) $id);
        if (!$temp || (int) $temp->member_id !== (int) $memberId) {
            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('temporary_members', [
            '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('temporary.removed', [
            'member_id'    => (int) $memberId,
            'temporary_id' => (int) $id,
            'reason'       => $reason,
        ]);

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