<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Auth;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class ProjectCharterTask extends Model implements HasMedia
{
    use HasFactory, InteractsWithMedia;

    protected $fillable = [
        'name',
        'description',
        'start_date',
        'end_date',
        'progress_percentage',
        'estimated_cost',
        'actual_cost',
        'project_charter_deliverable_id',
        'created_by',
    ];

    protected $casts = [
        'start_date' => 'datetime',
        'end_date' => 'datetime',
        'completed_date' => 'datetime',
        'estimated_cost' => 'decimal:2',
        'actual_cost' => 'decimal:2',
        'progress_percentage' => 'decimal:2',
    ];

    public function deliverable(): BelongsTo
    {
        return $this->belongsTo(ProjectCharterDeliverable::class, 'project_charter_deliverable_id');
    }

    public function assignedUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'assigned_user_id');
    }

    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    // status based on progress percentage
    public function getStatus(): string
    {
        if ($this->progress_percentage >= 100) {
            return 'completed';
        } elseif ($this->progress_percentage > 0) {
            return 'in_progress';
        } else {
            return 'pending';
        }
    }

    /**
     * Get the task status based on progress and dates
     */
    public function getStatusAttribute(): string
    {
        if ($this->progress_percentage >= 100) {
            return 'done';
        } elseif ($this->progress_percentage == 0) {
            return 'not_started';
        } elseif ($this->progress_percentage > 0 && $this->progress_percentage < 100) {
            // Check if late: in progress but past end date
            if ($this->end_date && now()->toDateString() > $this->end_date) {
                return 'late';
            }

            return 'in_progress';
        }

        return 'not_started'; // fallback
    }

    // Accessor for status badge color
    public function getStatusColorAttribute(): string
    {
        return match ($this->status) {
            'not_started' => 'gray',
            'in_progress' => 'blue',
            'late' => 'danger',
            'done' => 'success',
            default => 'gray',
        };
    }

    /**
     * Get available task statuses
     */
    public static function getTaskStatuses(): array
    {
        return [
            'not_started' => __('project_charter.task_status_not_started'),
            'in_progress' => __('project_charter.task_status_in_progress'),
            'late' => __('project_charter.task_status_late'),
            'done' => __('project_charter.task_status_done'),
        ];
    }

    // Check if task is overdue
    public function getIsOverdueAttribute(): bool
    {
        return $this->end_date &&
            $this->end_date < now()->toDateString() &&
            $this->getStatus() !== 'completed';
    }

    /**
     * Calculate estimated progress percentage based on start_date, end_date, and current date
     */
    public function getEstimatedProgressPercentageAttribute(): float
    {
        if (! $this->start_date || ! $this->end_date) {
            return 0;
        }

        $startDate = $this->start_date;
        $endDate = $this->end_date;
        $today = Carbon::today();

        // If today is before start date, estimated progress is 0%
        if ($today->lt($startDate)) {
            return 0;
        }

        // If today is after end date, estimated progress is 100%
        if ($today->gte($endDate)) {
            return 100;
        }

        // Calculate estimated progress based on time elapsed
        $totalDays = $startDate->diffInDays($endDate);
        $elapsedDays = $startDate->diffInDays($today);

        if ($totalDays == 0) {
            return 100;
        }

        return round(($elapsedDays / $totalDays) * 100, 1);
    }

    /**
     * Calculate progress deviation (difference between estimated and actual progress)
     */
    public function getProgressDeviationAttribute(): float
    {
        $estimatedProgress = $this->estimated_progress_percentage;
        $actualProgress = $this->progress_percentage ?? 0;

        return round(abs($estimatedProgress - $actualProgress), 1);
    }

    /**
     * Get color code for estimated progress percentage
     */
    public function getEstimatedProgressColorAttribute(): string
    {
        if (! $this->start_date || ! $this->end_date) {
            return 'gray';
        }

        $startDate = $this->start_date;
        $endDate = $this->end_date;
        $today = Carbon::today();

        if ($today->lt($startDate)) {
            return 'secondary';
        }

        if ($today->gte($endDate)) {
            return 'danger';
        }

        $estimatedProgress = $this->estimated_progress_percentage;

        return match (true) {
            $estimatedProgress >= 75 => 'warning',
            $estimatedProgress >= 50 => 'info',
            $estimatedProgress > 0 => 'success',
            default => 'secondary',
        };
    }

    /**
     * Get color code for progress deviation
     */
    public function getProgressDeviationColorAttribute(): string
    {
        $deviation = $this->progress_deviation;

        return match (true) {
            $deviation <= 5 => 'success',
            $deviation <= 15 => 'warning',
            $deviation <= 30 => 'danger',
            default => 'gray',
        };
    }

    /**
     * Check if this task can be deleted
     * A task cannot be deleted if it's the only task for its deliverable
     */
    public function canBeDeleted(): bool
    {
        return $this->deliverable->tasks()->count() > 1;
    }

    /**
     * Register media collections for file uploads
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('task_files')
            ->acceptsMimeTypes([
                'application/pdf',
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
                'application/vnd.ms-excel',
                'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
                'image/jpeg',
                'image/png',
                'image/gif',
                'text/plain',
            ]);
    }

    /**
     * Register media conversions
     */
    public function registerMediaConversions(?Media $media = null): void
    {
        // Add any media conversions if needed (thumbnails, etc.)
    }

    /**
     * Check if task has any files
     */
    public function hasFiles(): bool
    {
        return $this->getMedia('task_files')->count() > 0;
    }

    /**
     * Get files count
     */
    public function getFilesCountAttribute(): int
    {
        return $this->getMedia('task_files')->count();
    }

    /**
     * Boot the model
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($model) {
            if (Auth::check()) {
                $model->created_by = Auth::id();
            }
        });

        static::deleting(function ($task) {
            if (! $task->canBeDeleted()) {
                throw new \Exception('Cannot delete the last task of a deliverable. Each deliverable must have at least one task.');
            }
        });
    }
}
