<?php

namespace App\Http\Controllers\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\ConfiguracionEmpresa;
use App\Services\CattleDeactivationService;
use App\Services\CattleLifeSheetService;
use App\Services\CattleLocationMovementService;
use App\Services\CattlePhotoService;
use App\Services\PastureService;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use InvalidArgumentException;

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

    public function catalog(): JsonResponse
    {
        return response()->json([
            'data' => [
                'statuses' => config('ranch.cattle_statuses'),
                'genders' => config('ranch.genders'),
                'ear_tag_types' => config('ranch.ear_tag_types'),
                'material_categories' => config('ranch.material_categories'),
                'pastures' => $this->pastureService->listForCatalog(),
                'default_min_gdp_kg_per_day' => config('ranch.weight_performance.min_gdp_kg_per_day', 0.5),
            ],
        ]);
    }

    public function index(Request $request): JsonResponse
    {
        $perPage = min(100, max(1, (int) $request->get('per_page', 20)));
        $query = Cattle::query()->with(['mother:id,ear_tag', 'pasture:id,name', 'activeFatteningLotAssignment.fatteningLot']);

        if ($request->filled('status')) {
            $query->where('status', $request->string('status'));
        } elseif ($request->boolean('active_only', true)) {
            $query->active();
        }

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

        if ($request->filled('pasture_id')) {
            $query->where('pasture_id', (int) $request->get('pasture_id'));
        } elseif ($pasture = trim((string) $request->get('pasture_location', ''))) {
            $query->where('pasture_location', 'like', '%'.$pasture.'%');
        }

        if ($request->get('location_type') === 'fattening') {
            $query->whereHas('activeFatteningLotAssignment');
        } elseif ($request->get('location_type') === 'pasture') {
            $query->whereDoesntHave('activeFatteningLotAssignment')
                ->whereNotNull('pasture_location')
                ->where('pasture_location', '!=', '');
        }

        return response()->json([
            'data' => $query->orderByRaw('ear_tag IS NULL')->orderBy('ear_tag')->orderByDesc('id')->paginate($perPage),
        ]);
    }

    public function search(Request $request): JsonResponse
    {
        $earTag = trim((string) $request->get('ear_tag', ''));
        if ($earTag === '') {
            return response()->json(['message' => 'Indique el número de arete.'], 422);
        }

        $cattle = Cattle::query()
            ->with(['mother:id,ear_tag', 'activeFatteningLotAssignment.fatteningLot', 'weightRecords' => fn ($q) => $q->limit(5)])
            ->where('ear_tag', $earTag)
            ->first();

        if (! $cattle) {
            return response()->json(['message' => 'No se encontró animal con ese arete.'], 404);
        }

        $payload = $cattle->toArray();
        $payload['location_label'] = $cattle->activeFatteningLotAssignment?->fatteningLot
            ? 'Engorda: '.$cattle->activeFatteningLotAssignment->fatteningLot->name
            : ($cattle->pasture_location ? 'Corral/pasto: '.$cattle->pasture_location : 'Sin ubicación');

        if ($cattle->isActive() && $request->filled('exit_weight_kg')) {
            $payload['deactivation_preview'] = $this->deactivationService->previewClosure(
                $cattle,
                (float) $request->get('exit_weight_kg'),
            );
        }

        return response()->json(['data' => $payload]);
    }

    public function store(StoreCattleRequest $request): JsonResponse
    {
        $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 response()->json(['data' => $cattle->load(['mother', 'pasture'])], 201);
    }

    public function show(Cattle $cattle): JsonResponse
    {
        return response()->json([
            'data' => $this->lifeSheetService->build($cattle),
        ]);
    }

    public function expedientePdf(Cattle $cattle)
    {
        $sheet = $this->lifeSheetService->build($cattle);
        $empresa = ConfiguracionEmpresa::obtenerConfiguracion()?->nombre_empresa ?? 'Control Ganadero';
        $earTag = preg_replace('/[^A-Za-z0-9_-]+/', '-', $sheet['animal']['ear_tag'] ?? 'animal');

        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('pdf.ranch_cattle_expediente', [
            'sheet' => $sheet,
            'empresa' => $empresa,
            'generated_at' => now()->format('Y-m-d H:i'),
        ])->setPaper('letter', 'portrait');

        return $pdf->download('expediente-'.$earTag.'.pdf');
    }

    public function uploadPhoto(Request $request, Cattle $cattle): JsonResponse
    {
        $validated = $request->validate([
            'photo' => ['required', 'image', 'mimes:jpeg,jpg,png,webp,gif', 'max:3072'],
        ]);

        $this->photoService->store($cattle, $request->file('photo'));

        return response()->json([
            'data' => [
                'photo_path' => $cattle->fresh()->photo_path,
                'photo_url' => $cattle->fresh()->photo_url,
            ],
            'message' => 'Foto actualizada.',
        ]);
    }

    public function deletePhoto(Cattle $cattle): JsonResponse
    {
        $this->photoService->delete($cattle);

        return response()->json([
            'data' => ['photo_url' => null],
            'message' => 'Foto eliminada.',
        ]);
    }

    public function update(UpdateCattleRequest $request, Cattle $cattle): JsonResponse
    {
        if (! $cattle->isActive()) {
            return response()->json(['message' => 'Solo se pueden editar animales activos.'], 422);
        }

        $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 response()->json(['message' => $e->getMessage()], 422);
                }
            }
            unset($validated['pasture_id'], $validated['pasture_location']);
        }

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

        return response()->json(['data' => $this->lifeSheetService->build($cattle->fresh())]);
    }

    public function deactivate(DeactivateCattleRequest $request, Cattle $cattle): JsonResponse
    {
        try {
            $updated = $this->deactivationService->deactivate(
                $cattle,
                $request->validated(),
                (int) auth()->id()
            );
        } catch (InvalidArgumentException $e) {
            return response()->json(['message' => $e->getMessage()], 422);
        }

        return response()->json(['data' => $updated]);
    }
}
