<?php

namespace App\Http\Controllers\Admin\Ranch;

use App\Http\Controllers\Controller;
use App\Http\Requests\DeactivateCattleRequest;
use App\Http\Requests\StoreCattleRequest;
use App\Http\Requests\UpdateCattleRequest;
use App\Models\Cattle;
use App\Models\Pasture;
use App\Services\CattleDeactivationService;
use App\Services\CattleLifeSheetService;
use App\Services\CattleLocationMovementService;
use App\Services\PastureService;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use InvalidArgumentException;

class CattlePageController extends Controller
{
    public function __construct(
        private readonly CattleDeactivationService $deactivationService,
        private readonly CattleLifeSheetService $lifeSheetService,
        private readonly CattleLocationMovementService $locationMovementService,
        private readonly PastureService $pastureService,
    ) {}

    public function index(Request $request): Response
    {
        $query = Cattle::query()->with(['mother:id,ear_tag', 'pasture:id,name']);

        $status = (string) $request->get('status', 'active');
        if ($status !== '' && $status !== 'all') {
            $query->where('status', $status);
        }

        if ($q = trim((string) $request->get('q', ''))) {
            $term = '%'.$q.'%';
            $query->where(function ($builder) use ($term) {
                $builder->where('ear_tag', 'like', $term)
                    ->orWhere('breed', 'like', $term);
            });
        }

        return Inertia::render('Ranch/Cattle/Index', [
            'cattle' => $query->orderBy('ear_tag')->paginate(20)->withQueryString(),
            'filters' => [
                'q' => $request->get('q', ''),
                'status' => $request->get('status', 'active'),
            ],
            'statuses' => config('ranch.cattle_statuses'),
        ]);
    }

    public function create(): Response
    {
        return Inertia::render('Ranch/Cattle/Form', [
            'cattle' => null,
            'catalog' => $this->catalog(),
        ]);
    }

    public function store(StoreCattleRequest $request): RedirectResponse
    {
        $validated = $request->validated();
        $pastureId = $validated['pasture_id'] ?? null;
        $pastureLocation = $validated['pasture_location'] ?? null;
        unset($validated['pasture_id'], $validated['pasture_location']);

        $cattle = Cattle::create($validated + ['status' => Cattle::STATUS_ACTIVE]);
        $this->pastureService->applyToCattle($cattle, $pastureId, $pastureLocation);
        $cattle->save();

        return redirect()
            ->route('admin.ranch.cattle.show', $cattle)
            ->with('success', 'Animal registrado correctamente.');
    }

    public function show(Cattle $cattle): Response
    {
        return Inertia::render('Ranch/Cattle/Show', [
            'sheet' => $this->lifeSheetService->build($cattle),
            'statuses' => config('ranch.cattle_statuses'),
            'genders' => config('ranch.genders'),
        ]);
    }

    public function edit(Cattle $cattle): Response
    {
        abort_unless($cattle->isActive(), 422, 'Solo se pueden editar animales activos.');

        return Inertia::render('Ranch/Cattle/Form', [
            'cattle' => $cattle->load(['mother:id,ear_tag', 'pasture:id,name']),
            'catalog' => $this->catalog(),
        ]);
    }

    public function update(UpdateCattleRequest $request, Cattle $cattle): RedirectResponse
    {
        if (! $cattle->isActive()) {
            return back()->with('error', 'Solo se pueden editar animales activos.');
        }

        $validated = $request->validated();

        if (array_key_exists('pasture_id', $validated) || array_key_exists('pasture_location', $validated)) {
            $newPastureId = $validated['pasture_id'] ?? $cattle->pasture_id;
            $newPastureLocation = $validated['pasture_location'] ?? $cattle->pasture_location;
            if ($newPastureId !== $cattle->pasture_id || $newPastureLocation !== $cattle->pasture_location) {
                try {
                    $this->locationMovementService->moveToPasture(
                        $cattle,
                        $newPastureId,
                        $newPastureLocation,
                        Carbon::today(),
                        $request->user()?->id,
                    );
                } catch (InvalidArgumentException $e) {
                    return back()->with('error', $e->getMessage());
                }
            }
            unset($validated['pasture_id'], $validated['pasture_location']);
        }

        if ($validated !== []) {
            $cattle->update($validated);
        }

        return redirect()
            ->route('admin.ranch.cattle.show', $cattle)
            ->with('success', 'Animal actualizado.');
    }

    public function deactivate(DeactivateCattleRequest $request, Cattle $cattle): RedirectResponse
    {
        try {
            $this->deactivationService->deactivate(
                $cattle,
                $request->validated(),
                (int) auth()->id()
            );
        } catch (InvalidArgumentException $e) {
            return back()->with('error', $e->getMessage());
        }

        return redirect()
            ->route('admin.ranch.cattle.index')
            ->with('success', 'Animal dado de baja.');
    }

    /**
     * @return array<string, mixed>
     */
    private function catalog(): array
    {
        return [
            'statuses' => config('ranch.cattle_statuses'),
            'genders' => config('ranch.genders'),
            'ear_tag_types' => config('ranch.ear_tag_types'),
            'pastures' => Pasture::query()->active()->orderBy('sort_order')->orderBy('name')->get(['id', 'name']),
            'mothers' => Cattle::query()->active()->where('gender', 'female')->orderBy('ear_tag')->get(['id', 'ear_tag']),
        ];
    }
}
