<?php
declare(strict_types=1);

namespace App\Modules\Cashier\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Cashier\Services\PaymentRequestService;
use App\Modules\Treasury\Services\TreasuryService;
use App\Modules\Treasury\Services\SessionService;
use App\Modules\Treasury\Services\CustodyService;

class CashierController extends Controller
{
    public function queue(Request $request): Response
    {
        $this->authorize('cashier.view_queue');
        $employee = App::getInstance()->currentEmployee();
        $treasury = TreasuryService::getMembershipTreasury();

        $filters = [
            'status'       => trim((string) $request->get('status', '')),
            'payment_type' => trim((string) $request->get('payment_type', '')),
            'search'       => trim((string) $request->get('search', '')),
        ];

        $requests = [];
        $currentSession = null;
        $custodyBalance = '0.00';

        if ($treasury) {
            $requests = TreasuryService::getQueueForTreasury((int) $treasury['id'], $filters);
            $currentSession = SessionService::getCurrentSession((int) $treasury['id'], (int) $employee->id);
            $custodyBalance = CustodyService::getCurrentBalance((int) $treasury['id'], (int) $employee->id);
        } else {
            $branch = App::getInstance()->currentBranch();
            $branchId = $branch ? (int) $branch['id'] : null;
            $requests = PaymentRequestService::getPendingQueue($branchId, $filters);
        }

        return $this->view('Cashier.Views.queue', [
            'requests'       => $requests,
            'filters'        => $filters,
            'currentSession' => $currentSession,
            'custodyBalance' => $custodyBalance,
            'treasury'       => $treasury,
        ]);
    }

    public function process(Request $request, string $id): Response
    {
        $this->authorize('cashier.process_payment');
        $db = App::getInstance()->db();

        $pr = $db->selectOne(
            "SELECT pr.*, m.full_name_ar as member_name, m.form_number, m.membership_number, m.phone_mobile,
                    e.full_name_ar as requested_by_name
             FROM payment_requests pr
             LEFT JOIN members m ON m.id = pr.member_id
             LEFT JOIN employees e ON e.id = pr.requested_by
             WHERE pr.id = ? AND pr.is_voided = 0",
            [(int) $id]
        );

        if (!$pr) {
            return $this->redirect('/cashier')->withError('طلب الدفع غير موجود');
        }
        if ($pr['status'] === 'completed') {
            return $this->redirect('/cashier')->withError('طلب الدفع مكتمل بالفعل');
        }

        // For death_fee: override display name with the recipient (wife), not the deceased
        if ($pr['payment_type'] === 'death_fee' && !empty($pr['notes'])) {
            $notesData = json_decode($pr['notes'], true);
            if (!empty($notesData['recipient_name'])) {
                $pr['member_name'] = $notesData['recipient_name'];
                $pr['membership_number'] = null;
                // Form number: try notes first, then fall back to death_cases table
                $pr['form_number'] = $notesData['form_number'] ?? null;
                if (empty($pr['form_number']) && $pr['related_entity_type'] === 'death_cases' && !empty($pr['related_entity_id'])) {
                    $dc = $db->selectOne("SELECT form_number FROM death_cases WHERE id = ?", [(int) $pr['related_entity_id']]);
                    $pr['form_number'] = $dc['form_number'] ?? null;
                }
            }
        }

        return $this->view('Cashier.Views.process', [
            'pr' => $pr,
        ]);
    }

    public function complete(Request $request, string $id): Response
    {
        $this->authorize('cashier.process_payment');
        $employee = App::getInstance()->currentEmployee();

        $paymentMethod = trim((string) $request->post('payment_method', 'cash'));
        if ($paymentMethod === '') {
            return $this->redirect('/cashier/' . $id)->withError('طريقة الدفع مطلوبة');
        }

        $treasury = TreasuryService::getMembershipTreasury();

        if ($treasury) {
            $currentSession = SessionService::getCurrentSession((int) $treasury['id'], (int) $employee->id);
            if (!$currentSession) {
                return $this->redirect('/cashier')->withError('يجب فتح وردية أولاً قبل التحصيل');
            }

            $result = TreasuryService::collectPayment((int) $currentSession['id'], (int) $id, $paymentMethod);
        } else {
            $result = PaymentRequestService::processRequest((int) $id, $paymentMethod);
        }

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

        $receiptId = $result['receipt_id'] ?? null;
        $printParam = $receiptId ? '?print_receipt=' . $receiptId : '';

        return $this->redirect('/cashier' . $printParam)->withSuccess(
            'تم تحصيل الدفعة — إيصال: ' . ($result['receipt_number'] ?? '')
        );
    }

    public function openSession(Request $request): Response
    {
        $this->authorize('cashier.process_payment');
        $employee = App::getInstance()->currentEmployee();
        $treasury = TreasuryService::getMembershipTreasury();

        if (!$treasury) {
            return $this->redirect('/cashier')->withError('لم يتم تعريف خزنة العضويات');
        }

        $result = SessionService::openSession((int) $treasury['id'], (int) $employee->id);

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

        return $this->redirect('/cashier')->withSuccess('تم فتح الوردية بنجاح — رقم: ' . ($result['session_number'] ?? ''));
    }

    public function closeSession(Request $request): Response
    {
        $this->authorize('cashier.process_payment');
        $employee = App::getInstance()->currentEmployee();
        $treasury = TreasuryService::getMembershipTreasury();

        if (!$treasury) {
            return $this->redirect('/cashier')->withError('لم يتم تعريف خزنة العضويات');
        }

        $currentSession = SessionService::getCurrentSession((int) $treasury['id'], (int) $employee->id);
        if (!$currentSession) {
            return $this->redirect('/cashier')->withError('لا توجد وردية مفتوحة');
        }

        $result = SessionService::closeSession((int) $currentSession['id']);

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

        return $this->redirect('/cashier')->withSuccess('تم إغلاق الوردية — إجمالي التحصيلات: ' . ($result['total_collected'] ?? '0.00'));
    }

    public function cancel(Request $request, string $id): Response
    {
        $this->authorize('cashier.cancel_request');

        $reason = trim((string) $request->post('reason', ''));
        $result = PaymentRequestService::cancelRequest((int) $id, $reason);

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

        $returnTo = trim((string) $request->post('return_to', ''));
        if ($returnTo !== '' && str_starts_with($returnTo, '/members/')) {
            return $this->redirect($returnTo)->withSuccess('تم إلغاء طلب الدفع');
        }

        return $this->redirect('/cashier')->withSuccess('تم إلغاء طلب الدفع');
    }

    public function requeue(Request $request, string $id): Response
    {
        $this->authorize('cashier.cancel_request');

        $result = PaymentRequestService::requeueRequest((int) $id);

        if (!$result['success']) {
            $returnTo = trim((string) $request->post('return_to', ''));
            if ($returnTo !== '' && str_starts_with($returnTo, '/members/')) {
                return $this->redirect($returnTo)->withError($result['error']);
            }
            return $this->redirect('/cashier')->withError($result['error']);
        }

        $returnTo = trim((string) $request->post('return_to', ''));
        if ($returnTo !== '' && str_starts_with($returnTo, '/members/')) {
            return $this->redirect($returnTo)->withSuccess('تم إعادة الطلب لطابور الدفع — رقم: ' . $result['request_number']);
        }

        return $this->redirect('/cashier')->withSuccess('تم إعادة الطلب لطابور الدفع — رقم: ' . $result['request_number']);
    }
}
