<?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;

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'];
        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'] ?? 'خطأ في حساب الرسوم');
        }

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

        $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'],
            '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'               => $feeCalc['total_fee'],
            'status'                  => 'requested',
            'notes'                   => $notes ?: null,
        ]);

        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 = $feeCalc['total_fee'] ?? '0.00';
        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($feeCalc['total_fee']));
    }

    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);
    }
}