<?php
declare(strict_types=1);

namespace App\Modules\Installments\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Payments\Services\PaymentService;

class InstallmentController extends Controller
{
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();
        $filters = [
            'search' => trim((string) $request->get('q', '')),
            'status' => $request->get('status', ''),
            'overdue_only' => $request->get('overdue_only', ''),
        ];
        $page = max(1, (int) $request->get('page', 1));
        $perPage = 25;
        $where = '1=1';
        $params = [];

        if (!empty($filters['status'])) { $where .= ' AND ip.status = ?'; $params[] = $filters['status']; }
        if (!empty($filters['search'])) {
            $where .= ' AND (m.full_name_ar LIKE ? OR m.membership_number LIKE ?)';
            $s = '%' . $filters['search'] . '%'; $params[] = $s; $params[] = $s;
        }

        $countRow = $db->selectOne("SELECT COUNT(*) as cnt FROM installment_plans ip JOIN members m ON m.id = ip.member_id WHERE {$where}", $params);
        $total = (int) ($countRow['cnt'] ?? 0);
        $offset = ($page - 1) * $perPage;

        $rows = $db->select(
            "SELECT ip.*, m.full_name_ar as member_name, m.membership_number,
                    (SELECT COALESCE(SUM(paid_amount), 0) FROM installment_schedule WHERE installment_plan_id = ip.id AND status = 'paid') as total_paid_installments,
                    (SELECT COUNT(*) FROM installment_schedule WHERE installment_plan_id = ip.id AND status = 'pending' AND due_date < CURDATE()) as overdue_count
             FROM installment_plans ip
             JOIN members m ON m.id = ip.member_id
             WHERE {$where}
             " . ($filters['overdue_only'] ? "HAVING overdue_count > 0" : "") . "
             ORDER BY ip.created_at DESC LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        $pagination = \App\Core\Pagination::paginate($total, $perPage, $page);

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

    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $plan = $db->selectOne(
            "SELECT ip.*, m.full_name_ar as member_name, m.membership_number
             FROM installment_plans ip JOIN members m ON m.id = ip.member_id WHERE ip.id = ?",
            [(int) $id]
        );
        if (!$plan) return $this->redirect('/installments')->withError('الخطة غير موجودة');

        $schedule = $db->select(
            "SELECT * FROM installment_schedule WHERE installment_plan_id = ? ORDER BY installment_number ASC",
            [(int) $id]
        );

        return $this->view('Installments.Views.show', [
            'plan'     => $plan,
            'schedule' => $schedule,
        ]);
    }

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

        $existingActive = $db->selectOne("SELECT * FROM installment_plans WHERE member_id = ? AND status = 'active'", [(int) $memberId]);

        return $this->view('Installments.Views.create', [
            'member'         => $member,
            'existingActive' => $existingActive,
        ]);
    }

    public function payInstallment(Request $request, string $planId, string $scheduleId): Response
    {
        $db = App::getInstance()->db();
        $plan = $db->selectOne("SELECT * FROM installment_plans WHERE id = ?", [(int) $planId]);
        if (!$plan) return $this->redirect('/installments')->withError('الخطة غير موجودة');

        $item = $db->selectOne("SELECT * FROM installment_schedule WHERE id = ? AND installment_plan_id = ?", [(int) $scheduleId, (int) $planId]);
        if (!$item || $item['status'] === 'paid') return $this->redirect("/installments/{$planId}")->withError('القسط غير موجود أو مدفوع');

        $amount = $item['amount'];
        $paymentMethod = trim((string) $request->post('payment_method', 'cash'));

        $result = PaymentService::processPayment([
            'member_id'           => (int) $plan['member_id'],
            'amount'              => $amount,
            'payment_type'        => 'installment',
            'payment_method'      => $paymentMethod,
            'related_entity_type' => 'installment_schedule',
            'related_entity_id'   => (int) $scheduleId,
            'description'         => 'قسط رقم ' . $item['installment_number'] . ' — خطة #' . $planId,
        ]);

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

        $db->update('installment_schedule', [
            'paid_amount' => $amount,
            'payment_id'  => $result['payment_id'],
            'status'      => 'paid',
            'paid_at'     => date('Y-m-d H:i:s'),
            'updated_at'  => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $scheduleId]);

        // Check if all paid → complete plan
        $remaining = $db->selectOne("SELECT COUNT(*) as cnt FROM installment_schedule WHERE installment_plan_id = ? AND status = 'pending'", [(int) $planId]);
        if ((int) ($remaining['cnt'] ?? 0) === 0) {
            $db->update('installment_plans', ['status' => 'completed', 'updated_at' => date('Y-m-d H:i:s')], '`id` = ?', [(int) $planId]);
        }

        EventBus::dispatch('installment.paid', ['plan_id' => (int) $planId, 'schedule_id' => (int) $scheduleId, 'member_id' => (int) $plan['member_id']]);

        return $this->redirect("/installments/{$planId}")->withSuccess('تم دفع القسط — إيصال: ' . $result['receipt_number']);
    }
}