<?php
declare(strict_types=1);

namespace App\Modules\Installments\Models;

use App\Core\Model;
use App\Core\App;
use App\Core\Pagination;

class InstallmentPlan extends Model
{
    protected static string $table = 'installment_plans';
    protected static string $primaryKey = 'id';
    protected static bool $timestamps = true;
    protected static bool $softDelete = false;
    protected static bool $dispatchEvents = true;

    protected static array $fillable = [
        'member_id', 'related_entity_type', 'related_entity_id',
        'total_amount', 'down_payment', 'remaining_balance',
        'interest_rate', 'total_interest', 'total_with_interest',
        'number_of_months', 'monthly_payment', 'start_date',
        'down_payment_receipt', 'cash_settlement_date', 'is_cash_settled',
        'status', 'notes',
    ];

    public static function getForMember(int $memberId): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT * FROM installment_plans WHERE member_id = ? ORDER BY created_at DESC",
            [$memberId]
        );
    }

    public static function getActiveForMember(int $memberId): ?array
    {
        $db = App::getInstance()->db();
        return $db->selectOne(
            "SELECT * FROM installment_plans WHERE member_id = ? AND status = 'active' ORDER BY created_at DESC LIMIT 1",
            [$memberId]
        );
    }

    public static function hasOverdue(int $memberId): bool
    {
        $db = App::getInstance()->db();
        $row = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM installment_schedule s
             JOIN installment_plans p ON p.id = s.installment_plan_id
             WHERE p.member_id = ? AND p.status = 'active' AND s.status = 'pending' AND s.due_date < CURDATE()",
            [$memberId]
        );
        return (int) ($row['cnt'] ?? 0) > 0;
    }

    public static function getOverdueCount(int $memberId): int
    {
        $db = App::getInstance()->db();
        $row = $db->selectOne(
            "SELECT COUNT(*) as cnt FROM installment_schedule s
             JOIN installment_plans p ON p.id = s.installment_plan_id
             WHERE p.member_id = ? AND p.status = 'active' AND s.status = 'pending' AND s.due_date < CURDATE()",
            [$memberId]
        );
        return (int) ($row['cnt'] ?? 0);
    }

    public static function search(array $filters, int $perPage = 25, int $page = 1): array
    {
        $db = App::getInstance()->db();
        $where = '1=1';
        $params = [];

        if (!empty($filters['status'])) {
            $where .= ' AND p.status = ?';
            $params[] = $filters['status'];
        }
        if (!empty($filters['member_id'])) {
            $where .= ' AND p.member_id = ?';
            $params[] = (int) $filters['member_id'];
        }
        if (!empty($filters['overdue_only'])) {
            $where .= ' AND EXISTS (SELECT 1 FROM installment_schedule s WHERE s.installment_plan_id = p.id AND s.status = \'pending\' AND s.due_date < CURDATE())';
        }
        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 p JOIN members m ON m.id = p.member_id WHERE {$where}",
            $params
        );
        $total = (int) ($countRow['cnt'] ?? 0);
        $offset = ($page - 1) * $perPage;

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

        return ['data' => $rows, 'pagination' => Pagination::paginate($total, $perPage, $page)];
    }
}