<?php

namespace App\Http\Controllers\Ranch;

use App\Http\Controllers\Controller;
use App\Models\FatteningLot;
use App\Models\FatteningLotFeedIntake;
use App\Services\FatteningLotFeedIntakeService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use InvalidArgumentException;

class FatteningLotFeedIntakeController extends Controller
{
    public function __construct(
        private readonly FatteningLotFeedIntakeService $feedIntakeService,
    ) {}

    public function index(Request $request, FatteningLot $fatteningLot): JsonResponse
    {
        $query = FatteningLotFeedIntake::query()
            ->where('fattening_lot_id', $fatteningLot->id)
            ->with(['items.materialType', 'user:id,name'])
            ->orderByDesc('intake_date');

        if ($request->filled('from') && $request->filled('to')) {
            $query->whereBetween('intake_date', [$request->date('from'), $request->date('to')]);
        }

        $rows = $query->get()->map(function (FatteningLotFeedIntake $intake) {
            return [
                ...$intake->toArray(),
                'cost_per_head' => $intake->costPerHead(),
            ];
        });

        $lastIntake = $rows->first();

        return response()->json([
            'data' => $rows,
            'meta' => [
                'feed_investment' => $this->feedIntakeService->investmentSummary($fatteningLot),
                'last_intake' => $lastIntake,
            ],
        ]);
    }

    public function store(Request $request, FatteningLot $fatteningLot): JsonResponse
    {
        $validated = $this->validatePayload($request);

        try {
            $intake = $this->feedIntakeService->create($fatteningLot, $validated, auth()->id());
        } catch (InvalidArgumentException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json([
            'data' => [
                ...$intake->toArray(),
                'cost_per_head' => $intake->costPerHead(),
            ],
            'meta' => [
                'feed_investment' => $this->feedIntakeService->investmentSummary($fatteningLot),
            ],
        ], 201);
    }

    public function update(
        Request $request,
        FatteningLot $fatteningLot,
        FatteningLotFeedIntake $feedIntake
    ): JsonResponse {
        $this->assertOwnsLot($fatteningLot, $feedIntake);
        $validated = $this->validatePayload($request, true);

        try {
            $intake = $this->feedIntakeService->update($feedIntake, $validated, auth()->id());
        } catch (InvalidArgumentException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json([
            'data' => [
                ...$intake->toArray(),
                'cost_per_head' => $intake->costPerHead(),
            ],
            'meta' => [
                'feed_investment' => $this->feedIntakeService->investmentSummary($fatteningLot),
            ],
        ]);
    }

    public function destroy(FatteningLot $fatteningLot, FatteningLotFeedIntake $feedIntake): JsonResponse
    {
        $this->assertOwnsLot($fatteningLot, $feedIntake);

        try {
            $this->feedIntakeService->delete($feedIntake);
        } catch (InvalidArgumentException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json([
            'message' => 'Ración eliminada.',
            'meta' => [
                'feed_investment' => $this->feedIntakeService->investmentSummary($fatteningLot),
            ],
        ]);
    }

    private function validatePayload(Request $request, bool $updating = false): array
    {
        return $request->validate([
            'intake_date' => [$updating ? 'sometimes' : 'required', 'date'],
            'notes' => ['nullable', 'string'],
            'items' => ['required', 'array', 'min:1'],
            'items.*.material_type_id' => ['required', 'integer', 'exists:material_types,id'],
            'items.*.quantity' => ['required', 'numeric', 'min:0.001'],
            'items.*.unit_price' => ['nullable', 'numeric', 'min:0'],
        ]);
    }

    private function assertOwnsLot(FatteningLot $lot, FatteningLotFeedIntake $intake): void
    {
        if ((int) $intake->fattening_lot_id !== (int) $lot->id) {
            abort(404);
        }
    }
}
