<?php
declare(strict_types=1);

namespace App\Modules\Transfers\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Transfers\Models\TransferRequest;
use App\Modules\Transfers\Services\SeparationFeeCalculator;
use App\Modules\Transfers\Services\TransferProcessor;
use App\Modules\Payments\Services\PaymentService;
use App\Modules\Cashier\Services\PaymentRequestService;
use App\Modules\Forms\Services\FormBridge;
use App\Modules\Rules\Services\RuleEngine;
use App\Modules\Members\Services\NationalIdParser;

class TransferController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'search'        => trim((string) $request->get('q', '')),
            'status'        => $request->get('status', ''),
            'transfer_type' => $request->get('transfer_type', ''),
        ];
        $page = max(1, (int) $request->get('page', 1));
        $result = TransferRequest::search($filters, 25, $page);

        return $this->view('Transfers.Views.index', [
            'rows'       => $result['data'],
            'pagination' => $result['pagination'],
            'filters'    => $filters,
        ]);
    }

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

        $children = $db->select("SELECT * FROM children WHERE member_id = ? AND is_archived = 0 AND status = 'active'", [(int) $memberId]);
        $spouses = $db->select("SELECT * FROM spouses WHERE member_id = ? AND is_archived = 0 AND status = 'active'", [(int) $memberId]);

        return $this->view('Transfers.Views.create', [
            'member'   => $member,
            'children' => $children,
            'spouses'  => $spouses,
        ]);
    }

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

        $transferType = trim($request->post('transfer_type', ''));
        $childId = $request->post('child_id') ? (int) $request->post('child_id') : null;
        $spouseId = $request->post('spouse_id') ? (int) $request->post('spouse_id') : null;
        $notes = trim($request->post('notes', ''));
        $paymentMethod = trim($request->post('payment_method', 'cash'));

        $validTypes = ['child_separation', 'child_mandatory_25', 'sports_conversion', 'cross_branch', 'full_transfer'];
        if (!in_array($transferType, $validTypes)) {
            return $this->redirect("/transfers/create/{$memberId}")->withError('نوع التحويل غير صالح');
        }

        if (in_array($transferType, ['child_separation', 'child_mandatory_25']) && !$childId) {
            return $this->redirect("/transfers/create/{$memberId}")->withError('يجب اختيار الابن/الابنة');
        }

        // Age validation: dependents under separation age cannot self-separate
        if ($transferType === 'child_separation' && $childId) {
            $child = $db->selectOne("SELECT * FROM children WHERE id = ? AND is_archived = 0", [$childId]);
            if ($child && !empty($child['date_of_birth'])) {
                $dob = new \DateTime($child['date_of_birth']);
                $now = new \DateTime();
                $age = (int) $now->diff($dob)->y;
                $separationAge = (int) (RuleEngine::getValue('CHILD_MANDATORY_SEPARATION_AGE', 'value') ?? 25);
                if ($age < $separationAge) {
                    return $this->redirect("/transfers/create/{$memberId}")->withError(
                        'لا يمكن فصل الملحق تحت سن ' . $separationAge . ' سنة. العمر الحالي: ' . $age . ' سنة. يتم الفصل الوجوبي عند بلوغ ' . $separationAge . ' سنة.'
                    );
                }
            }
        }

        // Calculate fees
        $qualCode = null;
        if ($childId) {
            $child = $child ?? $db->selectOne("SELECT * FROM children WHERE id = ?", [$childId]);
            // Use child's qualification if available, otherwise parent's
        }

        $feeCalc = SeparationFeeCalculator::calculate((int) $memberId, $childId, $qualCode);
        if (!($feeCalc['success'] ?? false)) {
            return $this->redirect("/transfers/create/{$memberId}")->withError($feeCalc['error'] ?? 'خطأ في حساب الرسوم');
        }

        // Companion validation: check if new owner brings extra dependents
        $targetSpousesCount = (int) $request->post('target_spouses_count', 0);
        $targetChildrenCount = (int) $request->post('target_children_count', 0);
        $targetChildrenAges = array_map('intval', $request->post('target_children_ages', []));
        $companionSurcharge = '0.00';
        $companionBreakdown = null;
        $sourceCompanionsCount = null;
        $targetCompanionsCount = null;

        if ($targetSpousesCount > 0 || $targetChildrenCount > 0) {
            $surchargeResult = SeparationFeeCalculator::calculateCompanionSurcharge(
                (int) $memberId,
                $targetSpousesCount,
                $targetChildrenCount,
                $targetChildrenAges
            );
            $companionSurcharge = $surchargeResult['surcharge'];
            $sourceCompanionsCount = $surchargeResult['source_count'];
            $targetCompanionsCount = $surchargeResult['target_count'];
            if (!empty($surchargeResult['breakdown'])) {
                $companionBreakdown = json_encode($surchargeResult['breakdown'], JSON_UNESCAPED_UNICODE);
            }
        }

        $totalWithSurcharge = bcadd($feeCalc['total_fee'], $companionSurcharge, 2);

        // For full_transfer: store recipient data in notes JSON
        $recipientData = null;
        if ($transferType === 'full_transfer') {
            $recipientFields = ['full_name_ar', 'full_name_en', 'national_id', 'date_of_birth', 'gender', 'nationality', 'qualification_id', 'phone_mobile', 'marital_status', 'religion', 'phone_home', 'email', 'emergency_name', 'emergency_phone', 'residence_address', 'area', 'governorate', 'occupation', 'job_title'];
            $recipientData = [];
            foreach ($recipientFields as $field) {
                $val = trim($request->post('recipient_' . $field, ''));
                if ($val !== '') {
                    $recipientData[$field] = $val;
                }
            }
            if (empty($recipientData['full_name_ar']) || empty($recipientData['national_id'])) {
                return $this->redirect("/transfers/create/{$memberId}")->withError('بيانات المستلم مطلوبة (الاسم والرقم القومي)');
            }
            $rNid = $recipientData['national_id'] ?? '';
            if ($rNid !== '' && strlen($rNid) === 14) {
                $parsed = NationalIdParser::parse($rNid);
                if ($parsed['is_valid']) {
                    $recipientData['date_of_birth'] = $parsed['dob'];
                    $recipientData['gender'] = $parsed['gender'];
                }
            }
        }

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

        // Build notes JSON with recipient data if full_transfer
        $notesJson = null;
        if ($transferType === 'full_transfer' && $recipientData) {
            $notesPayload = ['recipient_data' => $recipientData];
            if ($notes) $notesPayload['user_notes'] = $notes;
            $notesJson = json_encode($notesPayload, JSON_UNESCAPED_UNICODE);
        } else {
            $notesJson = $notes ?: null;
        }

        $transferReq = TransferRequest::create([
            'source_member_id'            => (int) $memberId,
            'transfer_type'               => $transferType,
            'child_id'                    => $childId,
            'spouse_id'                   => $spouseId,
            'source_membership_number'    => $member['membership_number'],
            'new_membership_value'        => $feeCalc['new_membership_value'],
            'source_companions_count'     => $sourceCompanionsCount,
            'target_companions_count'     => $targetCompanionsCount,
            'companion_surcharge'         => $companionSurcharge,
            'companion_surcharge_breakdown'=> $companionBreakdown,
            'years_since_acquisition'     => $feeCalc['years_since_acquisition'],
            'qualification_code'          => $feeCalc['qualification_code'],
            'fee_percentage'              => $feeCalc['fee_percentage'],
            'separation_fee'              => $feeCalc['separation_fee'],
            'form_fee'                    => $feeCalc['form_fee'],
            'annual_subscription_fee'     => $feeCalc['annual_subscription_fee'],
            'total_fee'                   => $totalWithSurcharge,
            'status'                      => 'requested',
            'notes'                       => $notesJson,
        ]);

        if (FormBridge::exists('TRANSFER_SEPARATION')) {
            FormBridge::submit('TRANSFER_SEPARATION', $request->all(), (int) $memberId, 'طلب فصل/تحويل');
        }

        EventBus::dispatch('transfer.requested', [
            'transfer_id' => (int) $transferReq->id,
            'member_id'   => (int) $memberId,
            'type'        => $transferType,
        ]);

        // Send payment to cashier queue
        $amount = $totalWithSurcharge;
        if (bccomp((string) $amount, '0', 2) > 0) {
            $result = PaymentRequestService::createRequest([
                'member_id'           => (int) $memberId,
                'amount'              => $amount,
                'payment_type'        => 'separation_fee',
                'related_entity_type' => 'transfer_requests',
                'related_entity_id'   => (int) $transferReq->id,
                'description_ar'      => 'رسوم تحويل/فصل — طلب #' . $transferReq->id,
            ]);

            if ($result['success']) {
                return $this->redirect("/transfers/{$transferReq->id}")->withSuccess(
                    'تم تقديم طلب التحويل/الفصل وإرسال طلب الدفع للخزينة — الإجمالي: ' . money($amount) . ' — رقم الطلب: ' . $result['request_number']
                );
            }

            return $this->redirect("/transfers/{$transferReq->id}")->withError(
                'تم تقديم الطلب لكن فشل إنشاء طلب الدفع: ' . ($result['error'] ?? 'خطأ غير معروف')
            );
        }

        return $this->redirect("/transfers/{$transferReq->id}")->withSuccess('تم تقديم طلب التحويل/الفصل — الإجمالي: ' . money($totalWithSurcharge));
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $transfer = $db->selectOne(
            "SELECT tr.*, m.full_name_ar as source_name, m.membership_number as source_number,
                    tm.full_name_ar as target_name, tm.membership_number as target_number,
                    c.full_name_ar as child_name, s.full_name_ar as spouse_name,
                    e.full_name_ar as approved_by_name
             FROM transfer_requests tr
             JOIN members m ON m.id = tr.source_member_id
             LEFT JOIN members tm ON tm.id = tr.target_member_id
             LEFT JOIN children c ON c.id = tr.child_id
             LEFT JOIN spouses s ON s.id = tr.spouse_id
             LEFT JOIN employees e ON e.id = tr.approved_by
             WHERE tr.id = ?",
            [(int) $id]
        );
        if (!$transfer) return $this->redirect('/transfers')->withError('طلب التحويل غير موجود');

        return $this->view('Transfers.Views.show', ['transfer' => $transfer]);
    }

    public function pay(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $transfer = $db->selectOne("SELECT * FROM transfer_requests WHERE id = ?", [(int) $id]);
        if (!$transfer) return $this->redirect('/transfers')->withError('الطلب غير موجود');
        if (in_array($transfer['status'], ['completed', 'fee_paid', 'rejected'])) {
            return $this->redirect("/transfers/{$id}")->withError('لا يمكن الدفع لهذا الطلب');
        }

        $amount = $transfer['total_fee'] ?? '0.00';
        if (bccomp((string) $amount, '0', 2) <= 0) {
            return $this->redirect("/transfers/{$id}")->withError('لا توجد رسوم مطلوبة');
        }

        $result = PaymentService::processPayment([
            'member_id'           => (int) $transfer['source_member_id'],
            'amount'              => $amount,
            'payment_type'        => 'separation_fee',
            'payment_method'      => $request->post('payment_method', 'cash'),
            'related_entity_type' => 'transfer_requests',
            'related_entity_id'   => (int) $id,
            'description'         => 'رسوم تحويل/فصل — طلب #' . $id,
        ]);

        if (!$result['success']) {
            return $this->redirect("/transfers/{$id}")->withError($result['error']);
        }

        $db->update('transfer_requests', [
            'status'     => 'fee_paid',
            'updated_at' => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        EventBus::dispatch('transfer.fee_paid', ['transfer_id' => (int) $id, 'payment_id' => $result['payment_id']]);

        return $this->redirect("/transfers/{$id}")->withSuccess('تم دفع رسوم التحويل — إيصال: ' . $result['receipt_number']);
    }

    public function approve(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $transfer = $db->selectOne("SELECT * FROM transfer_requests WHERE id = ? AND status = 'requested'", [(int) $id]);
        if (!$transfer) return $this->redirect('/transfers')->withError('الطلب غير موجود أو تم التعامل معه');

        $employee = App::getInstance()->currentEmployee();
        $boardNotes = trim($request->post('board_decision_notes', ''));

        $db->update('transfer_requests', [
            'status'               => 'approved',
            'approved_by'          => $employee ? (int) $employee->id : null,
            'approved_at'          => date('Y-m-d H:i:s'),
            'board_decision_notes' => $boardNotes ?: null,
            'updated_at'           => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        EventBus::dispatch('transfer.approved', ['transfer_id' => (int) $id]);

        return $this->redirect("/transfers/{$id}")->withSuccess('تمت الموافقة على طلب التحويل');
    }

    public function reject(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $transfer = $db->selectOne("SELECT * FROM transfer_requests WHERE id = ? AND status = 'requested'", [(int) $id]);
        if (!$transfer) return $this->redirect('/transfers')->withError('الطلب غير موجود');

        $reason = trim($request->post('reject_reason', ''));
        $employee = App::getInstance()->currentEmployee();

        $db->update('transfer_requests', [
            'status'               => 'rejected',
            'board_decision_notes' => $reason ?: 'مرفوض',
            'approved_by'          => $employee ? (int) $employee->id : null,
            'approved_at'          => date('Y-m-d H:i:s'),
            'updated_at'           => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        return $this->redirect('/transfers')->withSuccess('تم رفض طلب التحويل');
    }

    public function complete(Request $request, string $id): Response
    {
        $result = TransferProcessor::execute((int) $id);

        if (!$result['success']) {
            return $this->redirect("/transfers/{$id}")->withError($result['error']);
        }

        return $this->redirect("/transfers/{$id}")->withSuccess(
            'تم إتمام التحويل — رقم العضوية الجديد: ' . $result['new_number']
        );
    }

    public function preview(Request $request, string $memberId): Response
    {
        $feeCalc = SeparationFeeCalculator::calculate((int) $memberId);
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);

        return $this->view('Transfers.Views.preview', [
            'member'  => $member,
            'feeCalc' => $feeCalc,
        ]);
    }

    public function calculateFee(Request $request): Response
    {
        $memberId = (int) $request->post('member_id', 0);
        $childId = $request->post('child_id') ? (int) $request->post('child_id') : null;
        $qualCode = $request->post('qualification_code') ?: null;

        $result = SeparationFeeCalculator::calculate($memberId, $childId, $qualCode);
        return $this->json($result);
    }
}