<?php

namespace App\Services;

use App\Models\Cattle;
use App\Models\WeightRecord;
use Carbon\Carbon;

class WeightPerformanceReportService
{
    /**
     * @return array{
     *   min_gdp_threshold: float,
     *   days_without_weigh_alert: int,
     *   alert_count: int,
     *   alerts: list<array<string, mixed>>,
     *   all_active: list<array<string, mixed>>
     * }
     */
    public function generate(?float $minGdp = null, ?int $daysWithoutWeigh = null): array
    {
        $globalDefault = $minGdp ?? (float) config('ranch.weight_performance.min_gdp_kg_per_day', 0.5);
        $daysWithoutWeigh ??= (int) config('ranch.weight_performance.days_without_weigh_alert', 30);
        $today = Carbon::today();

        $cattleList = Cattle::query()
            ->active()
            ->with(['activeFatteningLotAssignment.fatteningLot'])
            ->orderBy('ear_tag')
            ->get();

        $rows = [];
        $alerts = [];

        foreach ($cattleList as $cattle) {
            $latest = WeightRecord::query()
                ->where('cattle_id', $cattle->id)
                ->orderByDesc('weighed_at')
                ->first();

            $previous = null;
            if ($latest) {
                $previous = WeightRecord::query()
                    ->where('cattle_id', $cattle->id)
                    ->where('weighed_at', '<', $latest->weighed_at)
                    ->orderByDesc('weighed_at')
                    ->first();
            }

            $daysSinceWeigh = $latest
                ? $latest->weighed_at->diffInDays($today)
                : null;

            $threshold = $cattle->resolvedMinGdpKgPerDay($globalDefault);

            $row = [
                'cattle_id' => $cattle->id,
                'ear_tag' => $cattle->ear_tag,
                'breed' => $cattle->breed,
                'gender' => $cattle->gender,
                'fattening_lot' => $cattle->activeFatteningLotAssignment?->fatteningLot?->name,
                'effective_min_gdp_kg_per_day' => $threshold,
                'gdp_target_source' => $cattle->gdpTargetSource($globalDefault),
                'last_weighed_at' => $latest?->weighed_at?->toDateString(),
                'last_weight_kg' => $latest ? (float) $latest->weight_kg : null,
                'previous_weight_kg' => $previous ? (float) $previous->weight_kg : null,
                'weight_gain_kg' => $latest?->weight_gain_kg !== null ? (float) $latest->weight_gain_kg : null,
                'daily_weight_gain' => $latest?->daily_weight_gain !== null ? (float) $latest->daily_weight_gain : null,
                'days_since_weigh' => $daysSinceWeigh,
                'alert_type' => null,
                'alert_message' => null,
            ];

            if (! $latest) {
                $row['alert_type'] = 'never_weighed';
                $row['alert_message'] = 'Sin pesajes registrados';
                $alerts[] = $row;
            } elseif ($daysSinceWeigh !== null && $daysSinceWeigh > $daysWithoutWeigh) {
                $row['alert_type'] = 'stale_weigh';
                $row['alert_message'] = "Sin pesar hace {$daysSinceWeigh} días";
                $alerts[] = $row;
            } elseif ($latest->daily_weight_gain === null) {
                $row['alert_type'] = 'no_gdp';
                $row['alert_message'] = 'Requiere al menos dos pesajes para calcular GDP';
            } elseif ((float) $latest->daily_weight_gain < $threshold) {
                $row['alert_type'] = 'low_gdp';
                $row['alert_message'] = 'GDP '.number_format((float) $latest->daily_weight_gain, 2)
                    .' < meta '.number_format($threshold, 2).' kg/día';
                $alerts[] = $row;
            }

            $rows[] = $row;
        }

        usort($rows, function ($a, $b) {
            $gdpA = $a['daily_weight_gain'] ?? 9999;
            $gdpB = $b['daily_weight_gain'] ?? 9999;

            return $gdpA <=> $gdpB;
        });

        return [
            'min_gdp_threshold' => $globalDefault,
            'uses_per_animal_gdp_targets' => true,
            'days_without_weigh_alert' => $daysWithoutWeigh,
            'alert_count' => count($alerts),
            'alerts' => $alerts,
            'all_active' => $rows,
        ];
    }
}
