<?php
declare(strict_types=1);

namespace App\Modules\Waiver\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Waiver\Models\WaiverRequest;
use App\Modules\Waiver\Services\WaiverProcessor;
use App\Modules\Rules\Services\RuleEngine;
use App\Modules\Payments\Services\PaymentService;
use App\Modules\Cashier\Services\PaymentRequestService;

class WaiverController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = ['search' => trim((string) $request->get('q', '')), 'status' => $request->get('status', '')];
        $page = max(1, (int) $request->get('page', 1));
        $result = WaiverRequest::search($filters, 25, $page);
        return $this->view('Waiver.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('العضو غير موجود');

        $membershipValue = $member['membership_value'] ?? '0.00';
        $waiverPctData = RuleEngine::get('WAIVER_FEE');
        $waiverPct = $waiverPctData['percentage'] ?? '30.00';
        $waiverFee = bcdiv(bcmul($membershipValue, $waiverPct, 4), '100', 2);

        // Count dependents
        $spouseCount = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM spouses WHERE member_id = ? AND is_archived = 0", [(int) $memberId])['cnt'] ?? 0);
        $childCount = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM children WHERE member_id = ? AND is_archived = 0", [(int) $memberId])['cnt'] ?? 0);
        $tempCount = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM temporary_members WHERE member_id = ? AND is_archived = 0", [(int) $memberId])['cnt'] ?? 0);
        $totalDependents = $spouseCount + $childCount + $tempCount;

        return $this->view('Waiver.Views.create', [
            'member'          => $member,
            'waiver_pct'      => $waiverPct,
            'waiver_fee'      => $waiverFee,
            'total_dependents'=> $totalDependents,
        ]);
    }

    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_number']) return $this->redirect("/members/{$memberId}")->withError('العضو ليس لديه رقم عضوية');

        $membershipValue = $member['membership_value'] ?? '0.00';
        $waiverPctData = RuleEngine::get('WAIVER_FEE');
        $waiverPct = $waiverPctData['percentage'] ?? '30.00';
        $waiverFee = bcdiv(bcmul($membershipValue, $waiverPct, 4), '100', 2);
        $paymentMethod = trim($request->post('payment_method', 'cash'));

        $spouseCount = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM spouses WHERE member_id = ? AND is_archived = 0", [(int) $memberId])['cnt'] ?? 0);
        $childCount = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM children WHERE member_id = ? AND is_archived = 0", [(int) $memberId])['cnt'] ?? 0);
        $tempCount = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM temporary_members WHERE member_id = ? AND is_archived = 0", [(int) $memberId])['cnt'] ?? 0);

        $waiver = WaiverRequest::create([
            'source_member_id'           => (int) $memberId,
            'membership_number'          => $member['membership_number'],
            'membership_value_at_waiver' => $membershipValue,
            'waiver_fee_percentage'      => $waiverPct,
            'waiver_fee_amount'          => $waiverFee,
            'original_dependent_count'   => $spouseCount + $childCount + $tempCount,
            'board_approval_required'    => 1,
            'status'                     => 'requested',
            'notes'                      => trim($request->post('notes', '')) ?: null,
        ]);

        EventBus::dispatch('waiver.requested', ['waiver_id' => (int) $waiver->id, 'member_id' => (int) $memberId]);

        // Send payment to cashier queue
        if (bccomp($waiverFee, '0', 2) > 0) {
            $result = PaymentRequestService::createRequest([
                'member_id'           => (int) $memberId,
                'amount'              => $waiverFee,
                'payment_type'        => 'waiver_fee',
                'related_entity_type' => 'waiver_requests',
                'related_entity_id'   => (int) $waiver->id,
                'description_ar'      => 'رسوم تنازل — طلب #' . $waiver->id,
            ]);

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

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

        return $this->redirect("/waivers/{$waiver->id}")->withSuccess('تم تقديم طلب التنازل — الرسوم: ' . money($waiverFee) . ' (' . $waiverPct . '%)');
    }

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $waiver = $db->selectOne(
            "SELECT wr.*, m.full_name_ar as source_name, tm.full_name_ar as target_name, e.full_name_ar as approved_by_name
             FROM waiver_requests wr JOIN members m ON m.id = wr.source_member_id
             LEFT JOIN members tm ON tm.id = wr.target_member_id
             LEFT JOIN employees e ON e.id = wr.approved_by
             WHERE wr.id = ?",
            [(int) $id]
        );
        if (!$waiver) return $this->redirect('/waivers')->withError('الطلب غير موجود');
        return $this->view('Waiver.Views.show', ['waiver' => $waiver]);
    }

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

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

        $result = PaymentService::processPayment([
            'member_id'           => (int) $waiver['source_member_id'],
            'amount'              => $amount,
            'payment_type'        => 'waiver_fee',
            'payment_method'      => $request->post('payment_method', 'cash'),
            'related_entity_type' => 'waiver_requests',
            'related_entity_id'   => (int) $id,
            'description'         => 'رسوم تنازل — طلب #' . $id,
        ]);

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

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

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

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

    public function approve(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $waiver = $db->selectOne("SELECT * FROM waiver_requests WHERE id = ? AND status = 'requested'", [(int) $id]);
        if (!$waiver) return $this->redirect('/waivers')->withError('الطلب غير صالح');

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

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

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

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

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

        $db->update('waiver_requests', [
            'status'       => 'rejected',
            '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('/waivers')->withSuccess('تم رفض طلب التنازل');
    }

    public function complete(Request $request, string $id): Response
    {
        // The target member must be created first (via member creation flow)
        // and linked to the waiver
        $db = App::getInstance()->db();
        $targetMemberId = (int) $request->post('target_member_id', 0);
        if ($targetMemberId > 0) {
            $db->update('waiver_requests', [
                'target_member_id' => $targetMemberId,
                'updated_at'       => date('Y-m-d H:i:s'),
            ], '`id` = ?', [(int) $id]);
        }

        $result = WaiverProcessor::execute((int) $id);
        if (!$result['success']) return $this->redirect("/waivers/{$id}")->withError($result['error']);

        return $this->redirect("/waivers/{$id}")->withSuccess('تم إتمام التنازل — العضوية نُقلت بنجاح');
    }
}