<?php

namespace App\Services;

use App\Models\FatteningLot;
use App\Models\FatteningLotFeedIntake;
use App\Models\WeightRecord;
use Carbon\Carbon;

class FatteningLotAnalyticsService
{
    public function __construct(
        private readonly FatteningLotPastureCostService $pastureCostService,
        private readonly RanchOpenLotsProjectionService $projectionService,
        private readonly FatteningLotService $fatteningLotService,
    ) {}

    /**
     * @return array<string, mixed>
     */
    public function forLot(FatteningLot $lot): array
    {
        $lot->load(['animals.cattle', 'feedIntakes.items']);

        $cattleIds = $lot->animals->pluck('cattle_id')->all();
        $weights = WeightRecord::query()
            ->whereIn('cattle_id', $cattleIds)
            ->orderBy('weighed_at')
            ->get()
            ->groupBy('cattle_id');

        $weightSeries = [];
        foreach ($lot->animals as $assignment) {
            $records = ($weights[$assignment->cattle_id] ?? collect())
                ->filter(fn ($w) => $w->weighed_at->greaterThanOrEqualTo($assignment->entry_date))
                ->values();

            $points = $records->map(fn ($w) => [
                'date' => $w->weighed_at->toDateString(),
                'weight_kg' => (float) $w->weight_kg,
                'gain_kg' => $w->weight_gain_kg !== null ? (float) $w->weight_gain_kg : null,
            ])->all();

            if ($points === []) {
                $points[] = [
                    'date' => $assignment->entry_date->toDateString(),
                    'weight_kg' => (float) $assignment->entry_weight_kg,
                    'gain_kg' => 0,
                ];
            }

            $lastRecord = $records->last();
            $currentWeight = (float) ($lastRecord?->weight_kg ?? $assignment->entry_weight_kg);
            $gain = max(0, $currentWeight - (float) $assignment->entry_weight_kg);

            $weightSeries[] = [
                'cattle_id' => $assignment->cattle_id,
                'ear_tag' => $assignment->cattle?->ear_tag,
                'entry_weight_kg' => (float) $assignment->entry_weight_kg,
                'current_weight_kg' => $currentWeight,
                'weight_gain_kg' => round($gain, 2),
                'last_weigh' => $lastRecord ? [
                    'weight_kg' => (float) $lastRecord->weight_kg,
                    'weighed_at' => $lastRecord->weighed_at->toDateString(),
                    'weight_gain_kg' => $lastRecord->weight_gain_kg !== null
                        ? (float) $lastRecord->weight_gain_kg
                        : null,
                    'daily_weight_gain' => $lastRecord->daily_weight_gain !== null
                        ? (float) $lastRecord->daily_weight_gain
                        : null,
                ] : null,
                'points' => $points,
            ];
        }

        $intakes = FatteningLotFeedIntake::query()
            ->where('fattening_lot_id', $lot->id)
            ->orderBy('intake_date')
            ->get();

        $cumulative = 0.0;
        $feedTimeline = $intakes->map(function ($intake) use (&$cumulative) {
            $cumulative += (float) $intake->total_cost;

            return [
                'date' => $intake->intake_date->toDateString(),
                'daily_cost' => (float) $intake->total_cost,
                'cumulative_cost' => round($cumulative, 2),
            ];
        })->values()->all();

        $feedCost = $cumulative;
        $healthCost = $this->fatteningLotService->healthCostForLot($lot);
        $pastureCost = $this->pastureCostService->accruedCost($lot);
        $heads = max(1, $lot->animals->count());

        $projection = $this->projectionService->projectionForLot($lot);

        return [
            'weight_series' => $weightSeries,
            'feed_timeline' => $feedTimeline,
            'investment_breakdown' => [
                'feed_cost' => round($feedCost, 2),
                'health_cost' => round($healthCost, 2),
                'pasture_cost' => $pastureCost,
                'total' => round($feedCost + $healthCost + $pastureCost, 2),
                'per_head' => round(($feedCost + $healthCost + $pastureCost) / $heads, 2),
            ],
            'projection' => $projection,
        ];
    }
}
