<?php
declare(strict_types=1);

namespace App\Modules\Rentals\Models;

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

class RentalContract extends Model
{
    protected static string $table = 'rental_contracts';
    protected static string $primaryKey = 'id';
    protected static bool $timestamps = true;
    protected static bool $softDelete = true;
    protected static bool $autoTrackAuthor = true;

    protected static array $fillable = [
        'contract_number',
        'entity_id',
        'facility_id',
        'activity_type',
        'start_date',
        'end_date',
        'total_units',
        'unit_rate',
        'time_tier',
        'subtotal',
        'discount_percentage',
        'discount_amount',
        'total_amount',
        'vat_percentage',
        'vat_amount',
        'utilities_percentage',
        'utilities_amount',
        'grand_total',
        'late_fee_type',
        'late_fee_rate',
        'escalation_type',
        'escalation_rate',
        'escalation_tiers_json',
        'utilities_mode',
        'utilities_rent_pct',
        'utilities_facility_pct',
        'facility_monthly_cost',
        'payment_due_day',
        'late_fee_bank_rate',
        'grace_period_months',
        'early_termination_months',
        'deposit_percentage',
        'deposit_amount',
        'deposit_status',
        'deposit_payment_id',
        'technical_report_submitted',
        'status',
        'approved_by',
        'approved_at',
        'terms_json',
        'notes',
    ];

    /**
     * Late fee types with Arabic labels.
     */
    public static function getLateFeeTtypes(): array
    {
        return [
            'none'    => 'لا يوجد',
            'daily'   => 'يومي',
            'weekly'  => 'أسبوعي',
            'monthly' => 'شهري',
        ];
    }

    /**
     * Escalation types with Arabic labels.
     */
    public static function getEscalationTypes(): array
    {
        return [
            'none'   => 'لا يوجد',
            'flat'   => 'موحد',
            'tiered' => 'متدرج',
        ];
    }

    /**
     * Utilities modes with Arabic labels.
     */
    public static function getUtilitiesModes(): array
    {
        return [
            'none'              => 'لا يوجد',
            'rent_pct'          => 'نسبة من الإيجار',
            'facility_cost_pct' => 'نسبة من تكلفة المرفق',
            'both'              => 'الاثنان معاً',
        ];
    }

    /**
     * Calculate monthly invoice amounts from a contract row.
     * Returns [base, utilities, vat, total].
     */
    public static function calcMonthlyInvoice(object|array $c): array
    {
        $total     = (float) (is_object($c) ? $c->total_amount        : ($c['total_amount']        ?? 0));
        $months    = (float) (is_object($c) ? ($c->contract_months ?? 1) : ($c['contract_months'] ?? 1));
        $utilsPct  = (float) (is_object($c) ? $c->utilities_percentage : ($c['utilities_percentage'] ?? 0));
        $vatPct    = (float) (is_object($c) ? $c->vat_percentage       : ($c['vat_percentage']       ?? 1));

        $startDate = is_object($c) ? ($c->start_date ?? '') : ($c['start_date'] ?? '');
        $endDate   = is_object($c) ? ($c->end_date   ?? '') : ($c['end_date']   ?? '');
        if ($startDate && $endDate) {
            $diff = (new \DateTimeImmutable($startDate))->diff(new \DateTimeImmutable($endDate));
            $months = max(1, ($diff->y * 12) + $diff->m + ($diff->d > 0 ? 1 : 0));
        }

        $base      = round($total / max(1, $months), 2);
        $utilities = round($base * ($utilsPct / 100), 2);
        $vat       = round(($base + $utilities) * ($vatPct / 100), 2);
        $invoiceTotal = round($base + $utilities + $vat, 2);

        return compact('base', 'utilities', 'vat', 'invoiceTotal');
    }

    /**
     * Get all contract statuses with Arabic labels.
     */
    public static function getStatuses(): array
    {
        return [
            'draft'            => 'مسودة',
            'pending_approval' => 'بانتظار الاعتماد',
            'approved'         => 'مُعتمد',
            'active'           => 'فعال',
            'completed'        => 'مكتمل',
            'cancelled'        => 'ملغى',
            'terminated'       => 'منهي',
        ];
    }

    /**
     * Get all deposit statuses with Arabic labels.
     */
    public static function getDepositStatuses(): array
    {
        return [
            'pending'            => 'قيد التحصيل',
            'collected'          => 'محصّل',
            'partially_refunded' => 'مسترد جزئياً',
            'refunded'           => 'مسترد',
        ];
    }

    /**
     * Get the Arabic label for a status key.
     */
    public static function getStatusLabel(string $status): string
    {
        $statuses = self::getStatuses();
        return $statuses[$status] ?? $status;
    }

    /**
     * Get the badge color for a contract status.
     */
    public static function getStatusColor(string $status): string
    {
        $colors = [
            'draft'            => '#6B7280',
            'pending_approval' => '#D97706',
            'approved'         => '#7C3AED',
            'active'           => '#059669',
            'completed'        => '#0284C7',
            'cancelled'        => '#DC2626',
            'terminated'       => '#991B1B',
        ];
        return $colors[$status] ?? '#6B7280';
    }

    /**
     * Get the Arabic label for a deposit status key.
     */
    public static function getDepositStatusLabel(string $status): string
    {
        $statuses = self::getDepositStatuses();
        return $statuses[$status] ?? $status;
    }

    /**
     * Get the badge color for a deposit status.
     */
    public static function getDepositStatusColor(string $status): string
    {
        $colors = [
            'pending'            => '#D97706',
            'collected'          => '#059669',
            'partially_refunded' => '#7C3AED',
            'refunded'           => '#0284C7',
        ];
        return $colors[$status] ?? '#6B7280';
    }

    /**
     * Decode terms_json into an associative array.
     */
    public function getTerms(): array
    {
        $raw = $this->terms_json;
        if (empty($raw)) {
            return [];
        }
        $decoded = json_decode($raw, true);
        return is_array($decoded) ? $decoded : [];
    }

    /**
     * Generate a contract number in RC-YYYYMM-XXXX format.
     */
    public static function generateNumber(): string
    {
        $prefix = 'RC-' . date('Ym') . '-';
        $db = App::getInstance()->db();
        $row = $db->selectOne(
            "SELECT contract_number FROM rental_contracts WHERE contract_number LIKE ? ORDER BY id DESC LIMIT 1",
            [$prefix . '%']
        );

        $nextSeq = 1;
        if ($row) {
            $number = is_object($row) ? $row->contract_number : ($row['contract_number'] ?? '');
            $parts = explode('-', (string) $number);
            $lastSeq = (int) ($parts[2] ?? 0);
            $nextSeq = $lastSeq + 1;
        }

        return $prefix . str_pad((string) $nextSeq, 4, '0', STR_PAD_LEFT);
    }

    /**
     * Search contracts with filters and pagination.
     */
    public static function search(array $filters, int $perPage = 25, int $page = 1): array
    {
        $query = static::query();

        if (!empty($filters['q'])) {
            $search = '%' . $filters['q'] . '%';
            $query = $query->whereRaw(
                '(`contract_number` LIKE ? OR `notes` LIKE ?)',
                [$search, $search]
            );
        }

        if (!empty($filters['entity_id'])) {
            $query = $query->where('entity_id', '=', (int) $filters['entity_id']);
        }

        if (!empty($filters['facility_id'])) {
            $query = $query->where('facility_id', '=', (int) $filters['facility_id']);
        }

        if (!empty($filters['status'])) {
            $query = $query->where('status', '=', $filters['status']);
        }

        $query = $query->orderBy('created_at', 'DESC');

        return $query->paginate($perPage, $page);
    }

    /**
     * Get all contracts for a specific entity.
     */
    public static function getForEntity(int $entityId): array
    {
        return static::query()
            ->where('entity_id', '=', $entityId)
            ->orderBy('created_at', 'DESC')
            ->get();
    }
}
