<?php

namespace App\Services;

use App\Models\Cattle;
use App\Models\CattleHealthEvent;
use App\Models\MaterialExpense;
use App\Models\MaterialType;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;

class CattleHealthEventService
{
    /**
     * @param  array<string, mixed>  $data
     */
    public function record(array $data, int $userId): CattleHealthEvent
    {
        $cattle = $this->resolveCattle($data);

        return DB::transaction(function () use ($data, $cattle, $userId) {
            $cost = isset($data['cost']) ? (float) $data['cost'] : null;
            $materialExpenseId = null;
            $materialTypeId = $data['material_type_id'] ?? null;

            if ($cost !== null && $cost > 0 && config('ranch.health.auto_material_expense', true)) {
                $expense = $this->createMaterialExpense($cattle, $data, $cost, $userId);
                $materialExpenseId = $expense->id;
                $materialTypeId = $expense->material_type_id;
            }

            return CattleHealthEvent::create([
                'cattle_id' => $cattle->id,
                'event_type' => $data['event_type'],
                'event_date' => $data['event_date'],
                'title' => $data['title'],
                'product_name' => $data['product_name'] ?? null,
                'cost' => $cost,
                'outcome' => $data['outcome'] ?? null,
                'notes' => $data['notes'] ?? null,
                'material_type_id' => $materialTypeId,
                'material_expense_id' => $materialExpenseId,
                'user_id' => $userId,
            ])->load([
                'cattle:id,ear_tag',
                'materialType:id,name,category',
                'materialExpense:id,total_cost,expense_date',
                'user:id,name',
            ]);
        });
    }

    /**
     * @param  array<string, mixed>  $data
     */
    private function createMaterialExpense(Cattle $cattle, array $data, float $cost, int $userId): MaterialExpense
    {
        $materialTypeId = $data['material_type_id'] ?? null;
        if (! $materialTypeId) {
            $materialTypeId = MaterialType::query()
                ->active()
                ->where('category', config('ranch.health.material_category', 'animal_health'))
                ->orderBy('name')
                ->value('id');
        }

        if (! $materialTypeId) {
            throw new InvalidArgumentException(
                'Indique el tipo de material de salud o configure al menos uno en catálogo (categoría Salud Animal).'
            );
        }

        $lotId = $cattle->activeFatteningLotAssignment?->fattening_lot_id;
        $earTag = $cattle->ear_tag;
        $title = $data['title'];
        $product = $data['product_name'] ?? null;
        $quantity = isset($data['quantity']) && (float) $data['quantity'] > 0
            ? (float) $data['quantity']
            : 1.0;
        $noteParts = array_filter([
            "Salud arete {$earTag}: {$title}",
            $product ? "Producto: {$product}" : null,
            $quantity > 0 && $quantity !== 1.0 ? 'Dosis '.$quantity.' ml' : null,
            $data['notes'] ?? null,
        ]);

        return MaterialExpense::create([
            'material_type_id' => $materialTypeId,
            'expense_date' => $data['event_date'],
            'quantity' => round($quantity, 3),
            'unit_cost' => round($cost / $quantity, 4),
            'total_cost' => round($cost, 2),
            'fattening_lot_id' => $lotId,
            'notes' => implode(' | ', $noteParts),
            'user_id' => $userId,
        ]);
    }

    /**
     * @param  array<string, mixed>  $data
     */
    private function resolveCattle(array $data): Cattle
    {
        if (! empty($data['cattle_id'])) {
            return Cattle::query()
                ->with('activeFatteningLotAssignment')
                ->findOrFail($data['cattle_id']);
        }

        $earTag = trim((string) ($data['ear_tag'] ?? ''));
        $cattle = Cattle::query()
            ->with('activeFatteningLotAssignment')
            ->where('ear_tag', $earTag)
            ->first();

        if (! $cattle) {
            throw new InvalidArgumentException('No se encontró animal con arete '.$earTag);
        }

        return $cattle;
    }
}
