<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Support\Facades\Auth;
use Monzer\FilamentWorkflows\Traits\TrackWorkflowModelEvents;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class ProjectCharterEscalationRequest extends Model implements HasMedia
{
    use HasFactory, InteractsWithMedia, LogsActivity, TrackWorkflowModelEvents;

    const STATUS_PENDING = 'pending';

    const STATUS_RESOLVED = 'resolved';

    const STATUS_ESCALATED_TO_LEVEL_2 = 'escalated_to_level_2';

    const STATUS_RESOLVED_LEVEL_2 = 'resolved_level_2';

    protected $fillable = [
        'project_charter_id',
        'risk_register_id',
        'problem',
        'details',
        'status',
        'requested_by',
        'level_1_reviewed_by',
        'level_1_resolution_notes',
        'level_1_resolved_at',
        'level_2_reviewed_by',
        'level_2_resolution_notes',
        'level_2_resolved_at',
    ];

    protected $casts = [
        'level_1_resolved_at' => 'datetime',
        'level_2_resolved_at' => 'datetime',
    ];

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

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

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

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

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

    /**
     * Register media collections
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('escalation_attachments')
            ->acceptsMimeTypes([
                'application/pdf',
                'image/jpeg',
                'image/png',
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            ]);
    }

    /**
     * Register media conversions
     */
    public function registerMediaConversions(?Media $media = null): void
    {
        $this->addMediaConversion('thumb')
            ->width(300)
            ->height(300)
            ->sharpen(10)
            ->performOnCollections('escalation_attachments')
            ->nonQueued();
    }

    /**
     * Get available statuses
     */
    public static function getStatuses(): array
    {
        return [
            self::STATUS_PENDING => __('project_charter_escalation_request.status_pending'),
            self::STATUS_RESOLVED => __('project_charter_escalation_request.status_resolved'),
            self::STATUS_ESCALATED_TO_LEVEL_2 => __('project_charter_escalation_request.status_escalated_to_level_2'),
            self::STATUS_RESOLVED_LEVEL_2 => __('project_charter_escalation_request.status_resolved_level_2'),
        ];
    }

    /**
     * Check if request can be resolved at level 1
     */
    public function canResolveLevel1(): bool
    {
        return $this->status === self::STATUS_PENDING && Auth::user()->can('approve_level_1_escalation_project::charter::escalation::request');
    }

    /**
     * Check if request can be escalated to level 2
     */
    public function canEscalateToLevel2(): bool
    {
        return $this->status === self::STATUS_PENDING && Auth::user()->can('approve_level_1_escalation_project::charter::escalation::request');
    }

    /**
     * Check if request can be resolved at level 2
     */
    public function canResolveLevel2(): bool
    {
        return $this->status === self::STATUS_ESCALATED_TO_LEVEL_2 && Auth::user()->can('approve_level_2_escalation_project::charter::escalation::request');
    }

    /**
     * Resolve the request at level 1
     */
    public function resolveLevel1(string $resolutionNotes): bool
    {
        if (! $this->canResolveLevel1()) {
            return false;
        }

        $this->status = self::STATUS_RESOLVED;
        $this->level_1_reviewed_by = Auth::id();
        $this->level_1_resolution_notes = $resolutionNotes;
        $this->level_1_resolved_at = now();

        $result = $this->save();

        if ($result) {
            // Log activity
            activity()
                ->performedOn($this)
                ->causedBy(Auth::user())
                ->event('resolved_level_1')
                ->withProperties([
                    'resolution_notes' => $resolutionNotes,
                ])
                ->log('Escalation request resolved at level 1');
        }

        return $result;
    }

    /**
     * Escalate the request to level 2
     */
    public function escalateToLevel2(string $escalationNotes = ''): bool
    {
        if (! $this->canEscalateToLevel2()) {
            return false;
        }

        $this->status = self::STATUS_ESCALATED_TO_LEVEL_2;
        $this->level_1_reviewed_by = Auth::id();
        $this->level_1_resolution_notes = $escalationNotes;
        $this->level_1_resolved_at = now();

        $result = $this->save();

        if ($result) {
            // Log activity
            activity()
                ->performedOn($this)
                ->causedBy(Auth::user())
                ->event('escalated_to_level_2')
                ->withProperties([
                    'escalation_notes' => $escalationNotes,
                ])
                ->log('Escalation request escalated to level 2');
        }

        return $result;
    }

    /**
     * Resolve the request at level 2
     */
    public function resolveLevel2(string $resolutionNotes): bool
    {
        if (! $this->canResolveLevel2()) {
            return false;
        }

        $this->status = self::STATUS_RESOLVED_LEVEL_2;
        $this->level_2_reviewed_by = Auth::id();
        $this->level_2_resolution_notes = $resolutionNotes;
        $this->level_2_resolved_at = now();

        $result = $this->save();

        if ($result) {
            // Log activity
            activity()
                ->performedOn($this)
                ->causedBy(Auth::user())
                ->event('resolved_level_2')
                ->withProperties([
                    'resolution_notes' => $resolutionNotes,
                ])
                ->log('Escalation request resolved at level 2');
        }

        return $result;
    }

    /**
     * Get the current reviewer based on status
     */
    public function getCurrentReviewer(): ?User
    {
        return match ($this->status) {
            self::STATUS_PENDING => null,
            self::STATUS_RESOLVED => $this->level1ReviewedBy,
            self::STATUS_ESCALATED_TO_LEVEL_2 => $this->level1ReviewedBy,
            self::STATUS_RESOLVED_LEVEL_2 => $this->level2ReviewedBy,
            default => null,
        };
    }

    /**
     * Get the final resolution notes
     */
    public function getFinalResolutionNotes(): ?string
    {
        return match ($this->status) {
            self::STATUS_RESOLVED => $this->level_1_resolution_notes,
            self::STATUS_RESOLVED_LEVEL_2 => $this->level_2_resolution_notes,
            default => null,
        };
    }

    /**
     * Check if the escalation is fully resolved
     */
    public function isResolved(): bool
    {
        return in_array($this->status, [self::STATUS_RESOLVED, self::STATUS_RESOLVED_LEVEL_2]);
    }

    /**
     * Configure activity logging
     */
    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logOnly([
                'status',
                'problem',
                'details',
                'level_1_resolution_notes',
                'level_2_resolution_notes',
            ])
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs();
    }

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

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