<?php

namespace App\Domain\Website\Models;

use App\Domain\Documents\Models\Document;
use App\Domain\Identity\Models\User;
use App\Domain\Organization\Models\Branch;
use App\Domain\Organization\Models\Company;
use App\Domain\Recruitment\Models\Employer;
use App\Domain\Website\Enums\RequisitionStatus;
use App\Support\Concerns\HasUuid;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class EmployerRequisition extends Model
{
    use HasFactory, HasUuid, SoftDeletes;

    protected $guarded = ['id', 'uuid'];

    /** The token is a credential for the confirmation page; never serialise it. */
    protected $hidden = ['public_token'];

    protected function casts(): array
    {
        return [
            'status' => RequisitionStatus::class,
            'required_joining_date' => 'date',
            'application_deadline' => 'date',
            'preferred_interview_date' => 'date',
            'expected_deployment_date' => 'date',
            'submitted_at' => 'datetime',
            'reviewed_at' => 'datetime',
            'approved_at' => 'datetime',
            'converted_at' => 'datetime',
            'interview_required' => 'boolean',
            'employer_visiting' => 'boolean',
            'cv_shortlisting_required' => 'boolean',
            'trade_test_required' => 'boolean',
        ];
    }

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

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

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

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

    public function positions(): HasMany
    {
        return $this->hasMany(EmployerRequisitionPosition::class)->orderBy('sort_order');
    }

    /** Supporting files the employer attached to their submission (§144). */
    public function documents(): MorphMany
    {
        return $this->morphMany(Document::class, 'owner')->where('is_current', true);
    }

    public function statusHistories(): HasMany
    {
        return $this->hasMany(EmployerRequisitionStatusHistory::class)->latest('changed_at');
    }

    public function scopeOpen(Builder $query): Builder
    {
        return $query->whereIn('status', array_map(
            fn (RequisitionStatus $status) => $status->value,
            array_filter(RequisitionStatus::cases(), fn ($status) => $status->isOpen()),
        ));
    }

    /** Total workers requested across every position. */
    public function totalWorkers(): int
    {
        return (int) $this->positions->sum('quantity');
    }
}
