<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Lease extends Model
{
    protected $fillable = [
        'shop_id', 'tenant_id', 'start_date', 'grace_days', 'move_in_date',
        'end_date', 'agreed_rent', 'annual_increase_type', 'annual_increase_value',
        'initial_rent', 'initial_rent_months',
        'agreed_security_deposit', 'security_deposit_paid', 'maintenance_fee',
        'electricity_enabled', 'electricity_rate_per_unit',
        'agreement_file', 'agreement_notes', 'status',
        'commission_type', 'commission_amount', 'commission_to',
        'commission_phone', 'commission_paid', 'commission_paid_date',
        'commission_remarks',
    ];

    protected $casts = [
        'start_date' => 'date',
        'move_in_date' => 'date',
        'end_date' => 'date',
        'agreed_rent' => 'decimal:2',
        'annual_increase_value' => 'decimal:2',
        'initial_rent' => 'decimal:2',
        'agreed_security_deposit' => 'decimal:2',
        'security_deposit_paid' => 'decimal:2',
        'maintenance_fee' => 'decimal:2',
        'electricity_rate_per_unit' => 'decimal:2',
        'electricity_enabled' => 'boolean',
        'grace_days' => 'integer',
        'initial_rent_months' => 'integer',
        'commission_amount' => 'decimal:2',
        'commission_paid' => 'boolean',
        'commission_paid_date' => 'date',
    ];

    protected static function booted(): void
    {
        static::creating(function (Lease $lease) {
            if ($lease->grace_days > 0 && $lease->start_date) {
                $lease->move_in_date = Carbon::parse($lease->start_date)->subDays($lease->grace_days);
            } else {
                $lease->move_in_date = $lease->start_date;
            }
        });
    }

    public function shop(): BelongsTo
    {
        return $this->belongsTo(Shop::class);
    }

    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    public function invoices(): HasMany
    {
        return $this->hasMany(Invoice::class);
    }

    public function meterReadings(): HasMany
    {
        return $this->hasMany(MeterReading::class);
    }

    public function securityDepositPayments(): HasMany
    {
        return $this->hasMany(SecurityDepositPayment::class);
    }

    // Scope: active leases only
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    // Get the correct rent for a given month
    public function getRentForMonth(string $month): float
    {
        // Check initial rent discount period first
        if ($this->initial_rent && $this->initial_rent_months) {
            $startMonth = Carbon::parse($this->start_date)->format('Y-m');
            $monthsDiff = Carbon::parse($month . '-01')->diffInMonths(Carbon::parse($startMonth . '-01'));

            if ($monthsDiff < $this->initial_rent_months) {
                return (float) $this->initial_rent;
            }
        }

        // Calculate annual increase
        $baseRent = (float) $this->agreed_rent;
        $startDate = Carbon::parse($this->start_date);
        $targetDate = Carbon::parse($month . '-01');
        $yearsElapsed = (int) floor($startDate->diffInMonths($targetDate) / 12);

        if ($yearsElapsed > 0 && $this->annual_increase_value > 0) {
            if ($this->annual_increase_type === 'percentage') {
                for ($i = 0; $i < $yearsElapsed; $i++) {
                    $baseRent = $baseRent * (1 + (float) $this->annual_increase_value / 100);
                }
            } else {
                // fixed increase
                $baseRent = $baseRent + ($yearsElapsed * (float) $this->annual_increase_value);
            }
        }

        return round($baseRent, 2);
    }

    // Get current applicable rent (for display)
    public function getCurrentRentAttribute(): float
    {
        return $this->getRentForMonth(Carbon::now()->format('Y-m'));
    }

    // Security deposit remaining
    public function getSecurityDepositRemainingAttribute(): float
    {
        return (float) $this->agreed_security_deposit - (float) $this->security_deposit_paid;
    }

    // Check if currently in initial rent period
    public function getIsInitialRentPeriodAttribute(): bool
    {
        if (!$this->initial_rent || !$this->initial_rent_months) {
            return false;
        }

        $monthsDiff = Carbon::now()->diffInMonths(Carbon::parse($this->start_date));
        return $monthsDiff < $this->initial_rent_months;
    }

    // Check if in grace period
    public function getIsInGracePeriodAttribute(): bool
    {
        if ($this->grace_days <= 0) {
            return false;
        }

        $now = Carbon::now();
        return $now->gte($this->move_in_date) && $now->lt($this->start_date);
    }
}
