<?php

namespace App\Http\Controllers\Ranch;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreMaterialExpenseRequest;
use App\Models\MaterialExpense;
use App\Models\MaterialType;
use App\Services\FeedStockService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class MaterialExpenseController extends Controller
{
    public function __construct(
        private readonly FeedStockService $feedStockService,
    ) {}
    public function materialTypes(Request $request): JsonResponse
    {
        $query = MaterialType::query()->orderBy('category')->orderBy('name');

        if ($request->boolean('active_only', true)) {
            $query->active();
        }

        if ($request->filled('category')) {
            $query->where('category', $request->string('category'));
        }

        return response()->json([
            'data' => $query->get(),
        ]);
    }

    public function storeMaterialType(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'category' => ['required', 'string', 'in:'.implode(',', array_keys(config('ranch.material_categories')))],
            'name' => ['required', 'string', 'max:150'],
            'unit' => ['nullable', 'string', 'max:30'],
            'default_unit_price' => ['nullable', 'numeric', 'min:0'],
            'active' => ['sometimes', 'boolean'],
        ]);

        $type = MaterialType::create([
            ...$validated,
            'unit' => $validated['unit'] ?? 'kg',
            'active' => $validated['active'] ?? true,
        ]);

        return response()->json(['data' => $type], 201);
    }

    public function updateMaterialType(Request $request, MaterialType $materialType): JsonResponse
    {
        $validated = $request->validate([
            'name' => ['sometimes', 'string', 'max:150'],
            'unit' => ['sometimes', 'string', 'max:30'],
            'default_unit_price' => ['nullable', 'numeric', 'min:0'],
            'active' => ['sometimes', 'boolean'],
            'category' => ['sometimes', 'string', 'in:'.implode(',', array_keys(config('ranch.material_categories')))],
        ]);

        $materialType->update($validated);

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

    public function index(Request $request): JsonResponse
    {
        $query = MaterialExpense::query()
            ->with(['materialType', 'fatteningLot:id,name', 'user:id,name'])
            ->orderByDesc('expense_date');

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

        if ($request->filled('fattening_lot_id')) {
            $query->where('fattening_lot_id', $request->integer('fattening_lot_id'));
        }

        if ($request->filled('material_type_id')) {
            $query->where('material_type_id', $request->integer('material_type_id'));
        }

        if ($request->filled('scope')) {
            match ($request->string('scope')->toString()) {
                'feed_purchases' => $query
                    ->where('adds_to_inventory', true)
                    ->whereNull('fattening_lot_feed_intake_item_id')
                    ->whereHas('materialType', fn ($q) => $q->where('category', 'feed_supplements')),
                'health_applications' => $query
                    ->where('adds_to_inventory', false)
                    ->whereNull('fattening_lot_feed_intake_item_id')
                    ->whereHas('materialType', fn ($q) => $q->where('category', 'animal_health')),
                'health_purchases' => $query
                    ->where('adds_to_inventory', true)
                    ->whereHas('materialType', fn ($q) => $q->where('category', 'animal_health')),
                'health_all' => $query
                    ->whereHas('materialType', fn ($q) => $q->where('category', 'animal_health')),
                default => null,
            };
        } else {
            if ($request->boolean('purchases_only')) {
                $query->where('adds_to_inventory', true)
                    ->whereNull('fattening_lot_feed_intake_item_id');
            }

            if ($request->boolean('health_only')) {
                $query->whereHas('materialType', fn ($q) => $q->where('category', 'animal_health'));
            }

            if ($request->filled('health_mode')) {
                $query->whereHas('materialType', fn ($q) => $q->where('category', 'animal_health'));

                match ($request->string('health_mode')->toString()) {
                    'purchases' => $query->where('adds_to_inventory', true),
                    'applications' => $query->where('adds_to_inventory', false)
                        ->whereNull('fattening_lot_feed_intake_item_id'),
                    default => null,
                };
            }

            if ($request->filled('category')) {
                $query->whereHas('materialType', fn ($q) => $q->where('category', $request->string('category')));
            }
        }

        if ($request->boolean('all') || $request->input('all') === '1') {
            return response()->json([
                'data' => $query->limit(500)->get(),
            ]);
        }

        $perPage = min(100, max(5, $request->integer('per_page', 20)));

        return response()->json(['data' => $query->paginate($perPage)]);
    }

    public function store(StoreMaterialExpenseRequest $request): JsonResponse
    {
        $data = $request->validated();
        $qty = (float) $data['quantity'];
        $unit = (float) $data['unit_cost'];
        $type = MaterialType::findOrFail($data['material_type_id']);

        $addsToInventory = (bool) ($data['adds_to_inventory'] ?? false);
        if (! $addsToInventory && empty($data['fattening_lot_id']) && $type->category === 'feed_supplements') {
            $addsToInventory = true;
        }

        $expense = MaterialExpense::create([
            ...$data,
            'adds_to_inventory' => $addsToInventory,
            'total_cost' => round($qty * $unit, 2),
            'user_id' => auth()->id(),
        ]);

        if ($addsToInventory) {
            $this->feedStockService->addStock($type, $qty);
        }

        return response()->json(['data' => $expense->load('materialType', 'fatteningLot')], 201);
    }

    public function feedInventory(): JsonResponse
    {
        return response()->json(['data' => $this->feedStockService->feedInventory()]);
    }
}
