<?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 ProjectCharterChangeRequest extends Model implements HasMedia
{
    use HasFactory, InteractsWithMedia, LogsActivity, TrackWorkflowModelEvents;

    // Change types
    const CHANGE_TYPE_SCOPE = 'scope';

    const CHANGE_TYPE_DURATION = 'duration';

    const CHANGE_TYPE_COST = 'cost';

    // Status constants
    const STATUS_PENDING = 'pending';

    const STATUS_FIRST_APPROVED = 'first_approved'; // تأكيد

    const STATUS_APPROVED = 'approved'; // اعتماد (final approval)

    const STATUS_REJECTED = 'rejected';

    protected $fillable = [
        'project_charter_id',
        'change_type',
        'status',
        'justification',
        'new_start_date',
        'new_end_date',
        'additional_duration_days',
        'additional_cost',
        'cost_breakdown',
        'scope_changes',
        'includes_duration_change',
        'includes_cost_change',
        'requested_by',
        'reviewed_by',
        'review_notes',
        'reviewed_at',
        'first_approved_by',
        'first_approval_notes',
        'first_approved_at',
        'final_approved_by',
        'final_approval_notes',
        'final_approved_at',
    ];

    protected $casts = [
        'new_start_date' => 'datetime',
        'new_end_date' => 'datetime',
        'additional_cost' => 'decimal:2',
        'includes_duration_change' => 'boolean',
        'includes_cost_change' => 'boolean',
        'reviewed_at' => 'datetime',
        'first_approved_at' => 'datetime',
        'final_approved_at' => 'datetime',
    ];

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

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

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

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

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

    /**
     * Register media collections
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('change_request_attachments')
            ->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',
            ]);

        $this->addMediaCollection('final_approval_attachments')
            ->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',
            ]);
    }

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

    /**
     * Get available change types
     */
    public static function getChangeTypes(): array
    {
        return [
            self::CHANGE_TYPE_SCOPE => __('project_charter_change_request.change_type_scope'),
            self::CHANGE_TYPE_DURATION => __('project_charter_change_request.change_type_duration'),
            self::CHANGE_TYPE_COST => __('project_charter_change_request.change_type_cost'),
        ];
    }

    /**
     * Get available statuses
     */
    public static function getStatuses(): array
    {
        return [
            self::STATUS_PENDING => __('project_charter_change_request.status_pending'),
            self::STATUS_FIRST_APPROVED => __('project_charter_change_request.status_first_approved'),
            self::STATUS_APPROVED => __('project_charter_change_request.status_approved'),
            self::STATUS_REJECTED => __('project_charter_change_request.status_rejected'),
        ];
    }

    /**
     * Check if request can receive first approval (تأكيد)
     */
    public function canFirstApprove(): bool
    {
        return $this->status === self::STATUS_PENDING && Auth::user()->can('approve_change_request_project::charter::change::request');
    }

    /**
     * Check if request can receive final approval (اعتماد)
     */
    public function canFinalApprove(): bool
    {
        return $this->status === self::STATUS_FIRST_APPROVED && Auth::user()->can('final_approve_change_request_project::charter::change::request');
    }

    /**
     * Check if request can be rejected
     */
    public function canReject(): bool
    {
        return in_array($this->status, [self::STATUS_PENDING, self::STATUS_FIRST_APPROVED]) &&
            (Auth::user()->can('approve_change_request_project::charter::change::request') ||
                Auth::user()->can('final_approve_change_request_project::charter::change::request'));
    }

    /**
     * Legacy method for backward compatibility
     */
    public function canApprove(): bool
    {
        return $this->canFirstApprove() || $this->canFinalApprove();
    }

    /**
     * First approval (تأكيد)
     */
    public function firstApprove(string $approvalNotes = ''): bool
    {
        if (! $this->canFirstApprove()) {
            return false;
        }

        $this->status = self::STATUS_FIRST_APPROVED;
        $this->first_approved_by = Auth::id();
        $this->first_approval_notes = $approvalNotes;
        $this->first_approved_at = now();

        $result = $this->save();

        if ($result) {
            // Log activity
            activity()
                ->performedOn($this)
                ->causedBy(Auth::user())
                ->event('first_approved')
                ->withProperties([
                    'change_type' => $this->change_type,
                    'approval_notes' => $approvalNotes,
                ])
                ->log('Change request first approved (تأكيد)');
        }

        return $result;
    }

    /**
     * Final approval (اعتماد)
     */
    public function finalApprove(string $approvalNotes = ''): bool
    {
        if (! $this->canFinalApprove()) {
            return false;
        }

        $this->status = self::STATUS_APPROVED;
        $this->final_approved_by = Auth::id();
        $this->final_approval_notes = $approvalNotes;
        $this->final_approved_at = now();

        $result = $this->save();

        if ($result) {
            // Apply the changes to the project charter
            $this->applyChangesToCharter();

            // Log activity
            activity()
                ->performedOn($this)
                ->causedBy(Auth::user())
                ->event('final_approved')
                ->withProperties([
                    'change_type' => $this->change_type,
                    'approval_notes' => $approvalNotes,
                    'attachments_count' => $this->getFinalApprovalAttachments()->count(),
                ])
                ->log('Change request final approved (اعتماد)');
        }

        return $result;
    }

    /**
     * Legacy approve method for backward compatibility
     */
    public function approve(string $reviewNotes = ''): bool
    {
        // If pending, do first approval
        if ($this->status === self::STATUS_PENDING) {
            return $this->firstApprove($reviewNotes);
        }
        // If first approved, do final approval
        if ($this->status === self::STATUS_FIRST_APPROVED) {
            return $this->finalApprove($reviewNotes);
        }

        return false;
    }

    /**
     * Reject the change request
     */
    public function reject(string $reviewNotes): bool
    {
        if (! $this->canReject()) {
            return false;
        }

        $this->status = self::STATUS_REJECTED;
        $this->reviewed_by = Auth::id();
        $this->review_notes = $reviewNotes;
        $this->reviewed_at = now();

        $result = $this->save();

        if ($result) {
            // Log activity
            activity()
                ->performedOn($this)
                ->causedBy(Auth::user())
                ->event('rejected')
                ->withProperties([
                    'change_type' => $this->change_type,
                    'review_notes' => $reviewNotes,
                    'rejected_from_status' => $this->getOriginal('status'),
                ])
                ->log('Change request rejected');
        }

        return $result;
    }

    /**
     * Apply approved changes to the project charter
     */
    protected function applyChangesToCharter(): void
    {
        $charter = $this->projectCharter;
        $updates = [];

        switch ($this->change_type) {
            case self::CHANGE_TYPE_DURATION:
                if ($this->new_start_date) {
                    $updates['start_date'] = $this->new_start_date;
                }
                if ($this->new_end_date) {
                    $updates['expected_end_date'] = $this->new_end_date;
                }
                break;

            case self::CHANGE_TYPE_COST:
                if ($this->additional_cost) {
                    $updates['estimated_cost'] = $charter->estimated_cost + $this->additional_cost;
                }
                break;

            case self::CHANGE_TYPE_SCOPE:
                // For scope changes, we might update duration and/or cost if included
                if ($this->includes_duration_change) {
                    if ($this->new_start_date) {
                        $updates['start_date'] = $this->new_start_date;
                    }
                    if ($this->new_end_date) {
                        $updates['expected_end_date'] = $this->new_end_date;
                    }
                }
                if ($this->includes_cost_change && $this->additional_cost) {
                    $updates['estimated_cost'] = $charter->estimated_cost + $this->additional_cost;
                }
                break;
        }

        if (! empty($updates)) {
            $charter->update($updates);
        }
    }

    /**
     * Get summary of changes for display
     */
    public function getChangesSummary(): array
    {
        $summary = [];

        switch ($this->change_type) {
            case self::CHANGE_TYPE_DURATION:
                if ($this->additional_duration_days) {
                    $summary['duration'] = __('project_charter_change_request.additional_days', [
                        'days' => $this->additional_duration_days,
                    ]);
                }
                if ($this->new_end_date) {
                    $summary['new_end_date'] = $this->new_end_date->format('d M Y');
                }
                break;

            case self::CHANGE_TYPE_COST:
                if ($this->additional_cost) {
                    $summary['additional_cost'] = number_format((float) $this->additional_cost, 2).' SAR';
                }
                break;

            case self::CHANGE_TYPE_SCOPE:
                $summary['scope_changes'] = $this->scope_changes;
                if ($this->includes_duration_change && $this->additional_duration_days) {
                    $summary['duration'] = __('project_charter_change_request.additional_days', [
                        'days' => $this->additional_duration_days,
                    ]);
                }
                if ($this->includes_cost_change && $this->additional_cost) {
                    $summary['additional_cost'] = number_format((float) $this->additional_cost, 2).' SAR';
                }
                break;
        }

        return $summary;
    }

    /**
     * Get final approval attachments
     */
    public function getFinalApprovalAttachments()
    {
        return $this->getMedia('final_approval_attachments');
    }

    /**
     * Configure activity logging
     */
    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logOnly([
                'change_type',
                'status',
                'justification',
                'additional_cost',
                'additional_duration_days',
                'new_start_date',
                'new_end_date',
                'first_approved_by',
                'first_approval_notes',
                'first_approved_at',
                'final_approved_by',
                'final_approval_notes',
                'final_approved_at',
            ])
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs();
    }

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

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