<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Carbon;

class BailCondition extends Model
{
    use HasFactory;
    
    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'bail_application_id',
        'condition_type',
        'description',
        'requires_reporting',
        'police_station_id',
        'reporting_frequency',
        'reporting_days',
        'reporting_time_start',
        'reporting_time_end',
        'reporting_start_date',
        'reporting_end_date',
        'total_required_checkins',
        'completed_checkins',
        'is_fulfilled',
        'fulfillment_date',
        'fulfillment_notes',
        'verified_by',
        'created_by',
        'updated_by',
    ];
    
    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'is_fulfilled' => 'boolean',
        'requires_reporting' => 'boolean',
        'fulfillment_date' => 'date',
        'reporting_days' => 'array',
        'reporting_time_start' => 'datetime',
        'reporting_time_end' => 'datetime',
        'reporting_start_date' => 'date',
        'reporting_end_date' => 'date',
        'total_required_checkins' => 'integer',
        'completed_checkins' => 'integer',
    ];
    
    /**
     * Get the bail application that owns the condition.
     */
    public function bailApplication(): BelongsTo
    {
        return $this->belongsTo(BailApplication::class);
    }
    
    /**
     * Get the user who verified the condition fulfillment.
     */
    public function verifiedBy(): BelongsTo
    {
        return $this->belongsTo(User::class, 'verified_by');
    }
    
    /**
     * Get the user who created the condition.
     */
    public function createdByUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }
    
    /**
     * Get the user who last updated the condition.
     */
    public function updatedByUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'updated_by');
    }
    
    /**
     * Get the police station where the suspect must report.
     */
    public function policeStation(): BelongsTo
    {
        return $this->belongsTo(PoliceStation::class);
    }
    
    /**
     * Get the check-ins for this bail condition.
     */
    public function checkIns(): HasMany
    {
        return $this->hasMany(BailCheckin::class, 'bail_application_id', 'bail_application_id');
    }
    
    /**
     * Get the next scheduled check-in date.
     */
    public function getNextCheckInDateAttribute()
    {
        if (!$this->requires_reporting) {
            return null;
        }
        
        $today = Carbon::today();
        $nextDate = null;
        
        switch ($this->reporting_frequency) {
            case 'daily':
                $nextDate = $today;
                break;
                
            case 'weekly':
                $dayOfWeek = $this->reporting_days[0] ?? Carbon::MONDAY;
                $nextDate = $today->copy()->next($dayOfWeek);
                break;
                
            case 'biweekly':
                $dayOfWeek = $this->reporting_days[0] ?? Carbon::MONDAY;
                $nextDate = $today->copy()->next($dayOfWeek);
                // If today is the reporting day, check if we've already passed the reporting time
                if ($today->dayOfWeek == $dayOfWeek && Carbon::now()->greaterThan($this->reporting_time_end)) {
                    $nextDate = $today->copy()->addWeeks(2)->next($dayOfWeek);
                }
                break;
                
            case 'monthly':
                $dayOfMonth = $this->reporting_days[0] ?? 1;
                $nextDate = $today->copy()->day($dayOfMonth);
                if ($nextDate->lessThan($today)) {
                    $nextDate = $nextDate->addMonth();
                }
                break;
                
            case 'custom':
                // For custom schedules, we'd need to check the specific dates
                // This would require more complex logic based on your specific requirements
                break;
        }
        
        return $nextDate;
    }
    
    /**
     * Check if the suspect needs to check in today.
     */
    public function getRequiresCheckInTodayAttribute(): bool
    {
        if (!$this->requires_reporting) {
            return false;
        }
        
        $today = Carbon::today();
        
        // Check if today is within the reporting period
        if ($this->reporting_start_date && $today->lessThan($this->reporting_start_date)) {
            return false;
        }
        
        if ($this->reporting_end_date && $today->greaterThan($this->reporting_end_date)) {
            return false;
        }
        
        // Check based on frequency
        switch ($this->reporting_frequency) {
            case 'daily':
                return true;
                
            case 'weekly':
            case 'biweekly':
                $reportingDays = $this->reporting_days ?? [];
                return in_array($today->dayOfWeek, $reportingDays);
                
            case 'monthly':
                $reportingDays = $this->reporting_days ?? [];
                return in_array($today->day, $reportingDays);
                
            case 'custom':
                // For custom schedules, we'd need to check if today is a scheduled day
                // This would require more complex logic based on your specific requirements
                return false;
        }
        
        return false;
    }
    
    /**
     * Get the reporting schedule as a human-readable string.
     */
    public function getReportingScheduleTextAttribute(): string
    {
        if (!$this->requires_reporting) {
            return 'No reporting required';
        }
        
        $schedule = '';
        
        switch ($this->reporting_frequency) {
            case 'daily':
                $schedule = 'Daily';
                break;
                
            case 'weekly':
                $days = collect($this->reporting_days)->map(function ($day) {
                    return Carbon::create()->dayOfWeek($day)->format('l');
                })->join(', ');
                $schedule = "Weekly on {$days}";
                break;
                
            case 'biweekly':
                $days = collect($this->reporting_days)->map(function ($day) {
                    return Carbon::create()->dayOfWeek($day)->format('l');
                })->join(', ');
                $schedule = "Every two weeks on {$days}";
                break;
                
            case 'monthly':
                $days = collect($this->reporting_days)->map(function ($day) {
                    return $day . Carbon::create()->day($day)->format('S');
                })->join(', ');
                $schedule = "Monthly on the {$days} day";
                break;
                
            case 'custom':
                $schedule = 'Custom schedule';
                break;
        }
        
        if ($this->reporting_time_start && $this->reporting_time_end) {
            $timeStart = $this->reporting_time_start->format('h:i A');
            $timeEnd = $this->reporting_time_end->format('h:i A');
            $schedule .= " between {$timeStart} and {$timeEnd}";
        }
        
        if ($this->reporting_start_date && $this->reporting_end_date) {
            $startDate = $this->reporting_start_date->format('M j, Y');
            $endDate = $this->reporting_end_date->format('M j, Y');
            $schedule .= " from {$startDate} to {$endDate}";
        } elseif ($this->reporting_start_date) {
            $startDate = $this->reporting_start_date->format('M j, Y');
            $schedule .= " starting {$startDate}";
        }
        
        return $schedule;
    }
    
    /**
     * Get the status badge HTML.
     */
    public function getStatusBadgeAttribute(): string
    {
        return $this->is_fulfilled
            ? '<span class="badge badge-success">Fulfilled</span>'
            : '<span class="badge badge-warning">Pending</span>';
    }
    
    /**
     * Common condition types for dropdown lists.
     */
    public static function getConditionTypes(): array
    {
        return [
            'reporting' => 'Regular Reporting',
            'travel' => 'Travel Restrictions',
            'residence' => 'Fixed Residence',
            'contact' => 'No Contact with Witnesses',
            'curfew' => 'Curfew',
            'passport' => 'Surrender Passport',
            'employment' => 'Maintain Employment',
            'treatment' => 'Medical/Psychological Treatment',
            'other' => 'Other',
        ];
    }
}
