<?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 Illuminate\Support\Facades\Log;
use Monzer\FilamentWorkflows\Traits\TrackWorkflowModelEvents;
use Spatie\Activitylog\LogOptions;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

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

    const STATUS_PENDING = 'pending';

    const STATUS_ACCEPTED = 'accepted';

    const STATUS_REJECTED = 'rejected';

    const STATUS_ASK_MODIFICATION = 'ask_modification';

    const TECHNICAL_FINANCIAL_REQUIREMENTS = [
        'عرض فني ومالي 1',
        'عرض فني ومالي 2',
        'عرض فني ومالي 3',
    ];

    const ORDER_AGREEMENT_REQUIREMENT = 'نموذج اتفاقية الطلب';

    protected $fillable = [
        'name',
        'status',
        'order_id',
        'created_by',
    ];

    protected $casts = [
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    protected $attributes = [
        'status' => self::STATUS_PENDING,
    ];

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

    public function orderFinance(): \Illuminate\Database\Eloquent\Relations\HasOne
    {
        return $this->hasOne(OrderFinance::class);
    }

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

    /**
     * Get the authorization letter URL
     */
    public function getRequirementFileUrlAttribute(): ?string
    {
        return $this->getFirstMedia('requirement_file')?->getTemporaryUrl(Carbon::now()->addMinutes(30)) ?: null;
    }

    /**
     * Get available statuses
     */
    public static function getStatuses(): array
    {
        return [
            self::STATUS_PENDING => __('order_requirement.pending'),
            self::STATUS_ACCEPTED => __('order_requirement.accepted'),
            self::STATUS_REJECTED => __('order_requirement.rejected'),
            self::STATUS_ASK_MODIFICATION => __('order_requirement.ask_modification'),
        ];
    }

    /**
     * Get the technical and financial requirements array
     */
    public static function getTechnicalFinancialRequirements(): array
    {
        return self::TECHNICAL_FINANCIAL_REQUIREMENTS;
    }

    /**
     * Accept requirement
     */
    public function accept(string $notes = ''): void
    {
        $oldStatus = $this->status;
        $this->status = self::STATUS_ACCEPTED;
        $this->save();

        // If this is a technical and financial requirement, reject the other two
        if ($this->isTechnicalFinancialRequirement()) {
            $this->rejectOtherTechnicalFinancialRequirements();
        }

        if ($this->name === self::ORDER_AGREEMENT_REQUIREMENT) {
            // Replace order agreement file with the new one
            $this->replaceOrderAgreementFile();
        }

        // Log the acceptance activity
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('accepted')
            ->withProperties([
                'old_status' => $oldStatus,
                'new_status' => self::STATUS_ACCEPTED,
                'action' => 'accepted',
                'notes' => $notes,
            ])
            ->log('Order requirement accepted');
    }

    /**
     * Reject requirement
     */
    public function reject(string $notes = ''): void
    {
        $oldStatus = $this->status;
        $this->status = self::STATUS_REJECTED;
        $this->save();

        // Log the rejection activity
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('rejected')
            ->withProperties([
                'old_status' => $oldStatus,
                'new_status' => self::STATUS_REJECTED,
                'action' => 'rejected',
                'notes' => $notes,
            ])
            ->log('Order requirement rejected');
    }

    /**
     * Ask for modification
     */
    public function askModification(string $notes = ''): void
    {
        $oldStatus = $this->status;
        $this->status = self::STATUS_ASK_MODIFICATION;
        $this->save();

        // Log the ask modification activity
        activity()
            ->performedOn($this)
            ->causedBy(Auth::user())
            ->event('ask_modification')
            ->withProperties([
                'old_status' => $oldStatus,
                'new_status' => self::STATUS_ASK_MODIFICATION,
                'action' => 'ask_modification',
                'notes' => $notes,
            ])
            ->log('Order requirement modification requested');
    }

    /**
     * Check if this is a technical and financial requirement
     */
    protected function isTechnicalFinancialRequirement(): bool
    {
        return in_array($this->name, self::TECHNICAL_FINANCIAL_REQUIREMENTS);
    }

    /**
     * Reject other technical and financial requirements when one is accepted
     */
    protected function rejectOtherTechnicalFinancialRequirements(): void
    {
        // Get all technical and financial requirements for this order except the current one
        $otherRequirements = $this->order
            ->requirements()
            ->whereIn('name', self::TECHNICAL_FINANCIAL_REQUIREMENTS)
            ->where('id', '!=', $this->id)
            ->where('status', '!=', self::STATUS_REJECTED)
            ->get();

        foreach ($otherRequirements as $requirement) {
            $oldStatus = $requirement->status;
            $requirement->status = self::STATUS_REJECTED;
            $requirement->save();

            // Log the automatic rejection
            activity()
                ->performedOn($requirement)
                ->causedBy(Auth::user())
                ->event('auto_rejected')
                ->withProperties([
                    'old_status' => $oldStatus,
                    'new_status' => self::STATUS_REJECTED,
                    'action' => 'auto_rejected',
                    'reason' => 'Another technical and financial requirement was accepted',
                    'accepted_requirement' => $this->name,
                ])
                ->log('Order requirement automatically rejected due to another acceptance');
        }
    }

    /**
     * replace order agreement file with the new one from the order agreement requirement
     */
    protected function replaceOrderAgreementFile(): void
    {
        if (! $this->hasRequirementFile()) {
            return;
        }

        Log::info('Replacing order agreement file for order ID: '.$this->order_id);

        $this->getFirstMedia('requirement_file')
            ->copy($this->order, 'agreement_file');
    }

    public function hasRequirementFile(): bool
    {
        return $this->getFirstMedia('requirement_file') !== null;
    }

    /**
     * Register media collections for order requirements
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('requirement_file')
            ->singleFile()
            ->acceptsMimeTypes([
                'application/pdf',
                'image/jpeg',
                'image/png',
                'image/jpg',
            ]);
    }

    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->useLogName('order_requirement');
    }

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

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