<?php

namespace App\Models;

use App\Traits\BelongsToBranch;
use App\Traits\BelongsToTenant;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

class Application extends Model
{
    use BelongsToBranch, BelongsToTenant;

    protected $fillable = [
        'uuid',
        'tenant_id',
        'branch_id',
        'counter_id',
        'application_number',
        'draft_number',
        'customer_id',
        'applicant_type',
        'service_id',
        'service_version_id',
        'batch_id',
        'priority',
        'status',
        'current_stage_id',
        'assigned_user_id',
        'assigned_department_id',
        'payment_status',
        'document_status',
        'sla_status',
        'tracking_token',
        'gov_fee_total',
        'typing_fee_total',
        'service_charge_total',
        'vat_total',
        'total_price',
        'sla_start_at',
        'warning_at',
        'due_at',
        'created_by',
        'attended_by',
        'typed_by',
        'typing_started_at',
        'typing_completed_at',
        'completed_at',
        'cancelled_at',
        'archived_at',
        'workflow_started_at',
        'stage_entered_at',
        'sla_paused_at',
        'sla_pause_reason',
        'customer_notified_at',
        'output_status',
        'delivered_at',
        'delivered_by',
        'delivery_notes',
    ];

    protected $casts = [
        'sla_start_at' => 'datetime',
        'warning_at' => 'datetime',
        'due_at' => 'datetime',
        'completed_at' => 'datetime',
        'cancelled_at' => 'datetime',
        'workflow_started_at' => 'datetime',
        'stage_entered_at' => 'datetime',
        'sla_paused_at' => 'datetime',
        'customer_notified_at' => 'datetime',
        'delivered_at' => 'datetime',
        'typing_started_at' => 'datetime',
        'typing_completed_at' => 'datetime',
    ];

    protected static function boot()
    {
        parent::boot();
        static::creating(function ($model) {
            if (empty($model->uuid)) {
                $model->uuid = (string) Str::uuid();
            }
            if (empty($model->tracking_token)) {
                $model->tracking_token = 'TRK-'.Str::random(12);
            }
        });
    }

    public function customer()
    {
        return $this->belongsTo(Customer::class);
    }

    public function service()
    {
        return $this->belongsTo(Service::class);
    }

    public function serviceVersion()
    {
        return $this->belongsTo(ServiceVersion::class);
    }

    public function currentStage()
    {
        return $this->belongsTo(WorkflowStage::class, 'current_stage_id');
    }

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

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

    public function attendedBy()
    {
        return $this->belongsTo(User::class, 'attended_by');
    }

    public function typedByUser()
    {
        return $this->belongsTo(User::class, 'typed_by');
    }

    public function parties()
    {
        return $this->hasMany(ApplicationParty::class);
    }

    public function formValues()
    {
        return $this->hasMany(ApplicationFormValue::class);
    }

    public function documents()
    {
        return $this->hasMany(ApplicationDocument::class);
    }

    public function feeItems()
    {
        return $this->hasMany(ApplicationFeeItem::class);
    }

    public function invoiceItems()
    {
        return $this->hasMany(InvoiceItem::class);
    }

    public function stageHistory()
    {
        return $this->hasMany(ApplicationStageHistory::class)->latest();
    }

    public function submissions()
    {
        return $this->hasMany(ApplicationSubmission::class)->latest();
    }

    public function rejections()
    {
        return $this->hasMany(ApplicationRejection::class)->latest();
    }

    public function notes()
    {
        return $this->hasMany(ApplicationNote::class)->latest();
    }

    public function assignments()
    {
        return $this->hasMany(ApplicationAssignment::class)->latest();
    }

    public function outputs()
    {
        return $this->hasMany(ApplicationOutput::class)->latest();
    }

    public function slaPauses()
    {
        return $this->hasMany(ApplicationSlaPause::class)->latest();
    }

    public function deliveries()
    {
        return $this->hasMany(ApplicationDelivery::class)->latest();
    }

    public function deliveredByUser()
    {
        return $this->belongsTo(User::class, 'delivered_by');
    }

    public function workflowTasks()
    {
        return $this->hasMany(WorkflowTask::class, 'source_id')
            ->where('source_type', 'application')->latest();
    }

    public function communications()
    {
        return $this->hasMany(CommunicationLog::class)->latest();
    }
}
