<?php

namespace App\Services;

use App\Models\Cattle;
use App\Models\CattleLocationMovement;
use App\Models\CattleSaleIncome;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;

class CattleDeactivationService
{
    public function __construct(
        private readonly WeightRecordService $weightRecordService,
        private readonly CattleLifecycleSummaryService $lifecycleSummaryService,
        private readonly CattleLocationMovementService $locationMovementService,
    ) {}

    /**
     * @param  array{reason: string, exit_weight_kg: float, death_cause?: string, price_per_kg?: float, total_price?: float, sale_date?: string, notes?: string}  $data
     */
    public function deactivate(Cattle $cattle, array $data, int $userId): Cattle
    {
        if (! $cattle->isActive()) {
            throw new InvalidArgumentException('El animal no está activo en inventario.');
        }

        $reason = $data['reason'];
        $allowed = [Cattle::STATUS_SOLD, Cattle::STATUS_DEAD, Cattle::STATUS_CONSUMED];
        if (! in_array($reason, $allowed, true)) {
            throw new InvalidArgumentException('Motivo de baja no válido.');
        }

        return DB::transaction(function () use ($cattle, $data, $reason, $userId) {
            $exitWeight = (float) $data['exit_weight_kg'];
            $deactivatedAt = isset($data['sale_date'])
                ? Carbon::parse($data['sale_date'])
                : Carbon::today();

            $this->weightRecordService->record(
                $cattle,
                $exitWeight,
                $deactivatedAt,
                'Peso de salida — baja: '.$reason,
                $userId
            );

            $assignment = $cattle->activeFatteningAssignment();
            if ($assignment) {
                $assignment->load('fatteningLot');
                $lot = $assignment->fatteningLot;
                $assignment->update([
                    'exit_weight_kg' => $exitWeight,
                    'exit_date' => $deactivatedAt,
                    'removed_at' => $deactivatedAt,
                ]);
                if ($lot) {
                    $this->locationMovementService->record(
                        $cattle,
                        [
                            'type' => CattleLocationMovement::TYPE_FATTENING,
                            'label' => $lot->name,
                            'fattening_lot_id' => $lot->id,
                        ],
                        [
                            'type' => CattleLocationMovement::TYPE_UNASSIGNED,
                            'label' => null,
                            'fattening_lot_id' => null,
                        ],
                        CattleLocationMovement::REASON_DEACTIVATION,
                        $deactivatedAt,
                        $userId,
                        'Baja: '.$reason,
                    );
                }
            }

            $saleTotal = null;
            $pricePerKg = null;

            if ($reason === Cattle::STATUS_SOLD) {
                $pricePerKg = isset($data['price_per_kg']) ? (float) $data['price_per_kg'] : null;
                $saleTotal = isset($data['total_price'])
                    ? (float) $data['total_price']
                    : ($pricePerKg !== null ? round($pricePerKg * $exitWeight, 2) : null);

                if ($saleTotal === null || $saleTotal <= 0) {
                    throw new InvalidArgumentException('Debe indicar precio total o precio por kg para ventas.');
                }

                CattleSaleIncome::create([
                    'cattle_id' => $cattle->id,
                    'sale_date' => $deactivatedAt,
                    'exit_weight_kg' => $exitWeight,
                    'price_per_kg' => $pricePerKg,
                    'total_price' => $saleTotal,
                    'notes' => $data['notes'] ?? null,
                    'user_id' => $userId,
                ]);
            }

            $cattle->update([
                'status' => $reason,
                'deactivated_at' => $deactivatedAt,
                'deactivation_reason' => $reason,
                'death_cause' => $reason === Cattle::STATUS_DEAD ? ($data['death_cause'] ?? null) : null,
                'exit_weight_kg' => $exitWeight,
                'sale_price_per_kg' => $pricePerKg,
                'sale_total_price' => $saleTotal,
                'sale_date' => $reason === Cattle::STATUS_SOLD ? $deactivatedAt : null,
                'deactivated_by_user_id' => $userId,
            ]);

            $fresh = $cattle->fresh(['mother', 'weightRecords', 'fatteningLotAssignments.fatteningLot']);
            $fresh->setAttribute(
                'closure_summary',
                $this->lifecycleSummaryService->forDeactivation($fresh, $exitWeight, $deactivatedAt)
            );

            return $fresh;
        });
    }

    /**
     * Vista previa antes de confirmar la baja (sin persistir).
     *
     * @return array<string, mixed>
     */
    public function previewClosure(Cattle $cattle, float $exitWeightKg, ?Carbon $exitDate = null): array
    {
        return $this->lifecycleSummaryService->forDeactivation(
            $cattle,
            $exitWeightKg,
            $exitDate ?? Carbon::today()
        );
    }
}
