<?php

namespace App\Models;

use Database\Factories\AdoptionApplicationFactory;
use Illuminate\Database\Eloquent\Collection;
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\HasOne;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;

/**
 * @property int $id
 * @property int $user_id
 * @property int|null $pet_id
 * @property int|null $second_pet_id
 * @property string $status
 * @property string|null $cancellation_reason
 * @property array<int, string>|null $backfill_images
 * @property Carbon|null $created_at
 * @property Carbon|null $updated_at
 * @property-read Collection<int, ApplicationAnswer> $answers
 * @property-read int|null $answers_count
 * @property-read Interview|null $interview
 * @property-read Collection<int, AdoptionApplicationNote> $notes
 * @property-read int|null $notes_count
 * @property-read Pet|null $pet
 * @property-read Pet|null $secondPet
 * @property-read Collection<int, ApplicationStatusHistory> $statusHistory
 * @property-read int|null $status_history_count
 * @property-read User $user
 *
 * @method static \Database\Factories\AdoptionApplicationFactory factory($count = null, $state = [])
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication newModelQuery()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication newQuery()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication query()
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereBackfillImages($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereCancellationReason($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication wherePetId($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereSecondPetId($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereStatus($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereUpdatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder<static>|AdoptionApplication whereUserId($value)
 *
 * @mixin \Eloquent
 */
class AdoptionApplication extends Model
{
    /** @use HasFactory<AdoptionApplicationFactory> */
    use HasFactory;

    protected $fillable = [
        'user_id',
        'pet_id',
        'second_pet_id',
        'status',
        'cancellation_reason',
        'backfill_images',
    ];

    /**
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'backfill_images' => 'array',
        ];
    }

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

    protected static function booted(): void
    {
        static::deleting(function (AdoptionApplication $model): void {
            $model->answers()->delete();
        });
    }

    /**
     * @return BelongsTo<User, $this>
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * @return BelongsTo<Pet, $this>
     */
    public function pet(): BelongsTo
    {
        return $this->belongsTo(Pet::class);
    }

    /**
     * @return BelongsTo<Pet, $this>
     */
    public function secondPet(): BelongsTo
    {
        return $this->belongsTo(Pet::class, 'second_pet_id');
    }

    /**
     * @return HasMany<ApplicationStatusHistory, $this>
     */
    public function statusHistory(): HasMany
    {
        return $this->hasMany(ApplicationStatusHistory::class);
    }

    /**
     * @return HasOne<Interview, $this>
     */
    public function interview(): HasOne
    {
        return $this->hasOne(Interview::class);
    }

    /**
     * @return HasMany<AdoptionApplicationNote, $this>
     */
    public function notes(): HasMany
    {
        return $this->hasMany(AdoptionApplicationNote::class);
    }

    /**
     * @return MorphMany<ApplicationAnswer, $this>
     */
    public function answers(): MorphMany
    {
        return $this->morphMany(ApplicationAnswer::class, 'answerable')->orderBy('sort_order');
    }

    public function isFromLegacyMigration(): bool
    {
        return DB::table('legacy_adoption_migrations')
            ->where('new_adoption_application_id', $this->id)
            ->exists();
    }

    public function canModifyPetLink(): bool
    {
        if ($this->isFromLegacyMigration() && $this->status === 'archived') {
            return true;
        }

        return $this->status !== 'archived';
    }

    /**
     * Swap second pet to first position if first pet is null.
     * This ensures pet_id is always populated when pets exist.
     */
    public function swapPetsIfNeeded(): void
    {
        if ($this->second_pet_id && ! $this->pet_id) {
            $this->pet_id = $this->second_pet_id;
            $this->second_pet_id = null;
        }
    }

    /**
     * Check if this application references the given pet in either position.
     */
    public function hasPet(int $petId): bool
    {
        return $this->pet_id === $petId || $this->second_pet_id === $petId;
    }
}
