<?php

namespace App\Models;

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\Support\Facades\Storage;

class Cattle extends Model
{
    /** @use HasFactory<\Database\Factories\CattleFactory> */
    use HasFactory;

    public const STATUS_ACTIVE = 'active';

    public const STATUS_SOLD = 'sold';

    public const STATUS_DEAD = 'dead';

    public const STATUS_CONSUMED = 'consumed';

    protected $fillable = [
        'ear_tag',
        'ear_tag_type',
        'breed',
        'gender',
        'birth_date',
        'pasture_id',
        'pasture_location',
        'mother_id',
        'status',
        'notes',
        'photo_path',
        'target_min_gdp_kg_per_day',
        'deactivated_at',
        'deactivation_reason',
        'death_cause',
        'exit_weight_kg',
        'sale_price_per_kg',
        'sale_total_price',
        'sale_date',
        'deactivated_by_user_id',
    ];

    protected $casts = [
        'birth_date' => 'date',
        'deactivated_at' => 'date',
        'sale_date' => 'date',
        'exit_weight_kg' => 'decimal:2',
        'sale_price_per_kg' => 'decimal:2',
        'sale_total_price' => 'decimal:2',
        'target_min_gdp_kg_per_day' => 'decimal:4',
    ];

    protected $appends = [
        'photo_url',
        'display_ear_tag',
    ];

    public function getDisplayEarTagAttribute(): string
    {
        $tag = trim((string) ($this->attributes['ear_tag'] ?? ''));
        if ($tag !== '') {
            return $tag;
        }

        $birth = $this->birth_date?->format('Y-m-d');
        if ($birth) {
            return "Sin arete · nacido {$birth}";
        }

        return 'Sin arete · #'.$this->id;
    }

    public function getPhotoUrlAttribute(): ?string
    {
        if (! $this->photo_path) {
            return null;
        }

        return Storage::disk('public')->url($this->photo_path);
    }

    public function hasEarTag(): bool
    {
        return trim((string) ($this->attributes['ear_tag'] ?? '')) !== '';
    }

    public function resolvedMinGdpKgPerDay(?float $globalDefault = null): float
    {
        if ($this->target_min_gdp_kg_per_day !== null) {
            return (float) $this->target_min_gdp_kg_per_day;
        }

        $lot = $this->activeFatteningLotAssignment?->fatteningLot;
        if ($lot?->target_min_gdp_kg_per_day !== null) {
            return (float) $lot->target_min_gdp_kg_per_day;
        }

        return $globalDefault ?? (float) config('ranch.weight_performance.min_gdp_kg_per_day', 0.5);
    }

    public function gdpTargetSource(?float $globalDefault = null): string
    {
        if ($this->target_min_gdp_kg_per_day !== null) {
            return 'animal';
        }

        $lot = $this->activeFatteningLotAssignment?->fatteningLot;
        if ($lot?->target_min_gdp_kg_per_day !== null) {
            return 'lot';
        }

        return 'default';
    }

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

    public function mother(): BelongsTo
    {
        return $this->belongsTo(self::class, 'mother_id');
    }

    public function offspring(): HasMany
    {
        return $this->hasMany(self::class, 'mother_id');
    }

    public function calvingEventsAsMother(): HasMany
    {
        return $this->hasMany(CattleCalvingEvent::class, 'mother_id');
    }

    public function locationMovements(): HasMany
    {
        return $this->hasMany(CattleLocationMovement::class)->orderByDesc('moved_at');
    }

    public function weightRecords(): HasMany
    {
        return $this->hasMany(WeightRecord::class)->orderByDesc('weighed_at');
    }

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

    public function activeFatteningLotAssignment(): HasOne
    {
        return $this->hasOne(FatteningLotAnimal::class)
            ->whereNull('removed_at')
            ->latestOfMany('entry_date');
    }

    public function activeFatteningAssignment(): ?FatteningLotAnimal
    {
        return $this->activeFatteningLotAssignment;
    }

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

    public function healthEvents(): HasMany
    {
        return $this->hasMany(CattleHealthEvent::class)->orderByDesc('event_date');
    }

    public function isActive(): bool
    {
        return $this->status === self::STATUS_ACTIVE;
    }

    public function scopeActive($query)
    {
        return $query->where('status', self::STATUS_ACTIVE);
    }
}
