<?php

namespace App\Models;

use App\Enum\Esign\EsignStatus;
use App\Models\Client\Client;
use App\Models\User\User;
use App\Trait\BelongsToSolicitor;
use App\Trait\HasSlug;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

/**
 * A single "send these contracts for e-signature" action. Fans out into one
 * EsignDocument per selected (template-mapped) contract. Its `status` is an
 * aggregate derived from its documents.
 */
class ContractRequest extends Model {
    use HasSlug;
    use BelongsToSolicitor;

    protected $fillable = [
        'client_id',
        'solicitor_id',
        'user_id',
        'contract_ids',
        'status',
        'link',
        'full_data',
    ];

    protected $casts = [
        'contract_ids' => 'array',
        'full_data' => 'array',
        'status' => EsignStatus::class,
    ];

    protected $attributes = [
        'status' => 'draft',
    ];

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

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

    public function esignDocuments(): HasMany {
        return $this->hasMany(EsignDocument::class);
    }

    /**
     * Recompute the request-level status from its documents: the least-advanced
     * active document's status, or COMPLETED when all are completed; if every
     * document is a terminal failure, surface that failure.
     */
    public function recomputeStatus(): void {
        $docs = $this->esignDocuments()->get();

        if ($docs->isEmpty()) {
            return;
        }

        $active = $docs->reject(fn (EsignDocument $d) => $d->status->isTerminalFailure());

        $next = $active->isEmpty()
            ? $docs->sortByDesc(fn (EsignDocument $d) => $d->status->rank())->first()->status
            : $active->sortBy(fn (EsignDocument $d) => $d->status->rank())->first()->status;

        if ($this->status !== $next) {
            $this->forceFill(['status' => $next])->save();
        }
    }
}
