<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Input;
use App\Models\CostInput;
use App\Models\DepositInput;
use App\Models\KardexDeposit;
use App\Models\Unit;
use App\Models\Supplier;
use App\Models\Deposit;
use App\Models\Category;
use Illuminate\Support\Facades\DB;

class InputController extends Controller
{
    public function index(Request $request)
    {
        $perPage = $request->get('per_page', 10);
        $search = $request->get('search', '');

        $query = Input::with(['unit', 'category', 'supplier']);
        if ($search) {
            $query->where('name', 'like', "%{$search}%")
                  ->orWhere('codigo', 'like', "%{$search}%");
        }
        $inputs = $query->orderBy('id', 'desc')->paginate($perPage);

        return response()->json([
            'success' => true,
            'inputs' => $inputs
        ]);
    }

    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'codigo'            => 'nullable|string|max:100',
            'codigo_interno'    => 'nullable|string|max:100',
            'id_unit'           => 'required|integer|exists:unit_measures,id',
            'id_category'       => 'nullable|integer|exists:categories,id',
            'margen_ganancia'   => 'nullable|numeric',
            'id_supplier'       => 'nullable|integer|exists:suppliers,id',
            'igv'               => 'required|in:0,1',
            'igv_porcentaje'    => 'nullable|numeric',
            'stock'             => 'nullable|numeric',
            'name'              => 'required|string|max:255',
            'costos'            => 'nullable|array',
            'costos.*.cantidad'       => 'required|numeric',
            'costos.*.precio_compra'  => 'required|numeric',
            'costos.*.precio_venta'   => 'required|numeric',
            'costos.*.active'         => 'required|in:0,1',
            'costos.*.id_unit'        => 'required|integer|exists:unit_measures,id',
            'depositos'   => 'nullable|array',
            'depositos.*.id_deposit'    => 'required|integer|exists:deposits,id',
            'depositos.*.cantidad'      => 'required|numeric',
            'depositos.*.stock_minimo'  => 'required|numeric',
            'depositos.*.stock_maximo'  => 'required|numeric',
        ], [
            'name.required' => 'El nombre es obligatorio.',
            'costos.*.cantidad.required' => 'La cantidad es obligatoria en costos.',
            'costos.*.precio_compra.required' => 'El precio de compra es obligatorio en costos.',
            'costos.*.precio_venta.required' => 'El precio de venta es obligatorio en costos.',
            'depositos.*.id_deposit.required' => 'El depósito es obligatorio.',
        ]);

        DB::beginTransaction();
        try {
            $stockAnterior = 0;
            $stockActual = $validatedData['stock'] ?? 0;
            
            $input = Input::create($validatedData);

            // Registrar en kardex si se creó con stock inicial
            if ($stockActual > 0) {
                $this->registrarKardexDeposit(
                    $input->id,
                    'entrada',
                    'input_create',
                    $input->id,
                    $stockActual,
                    $stockAnterior,
                    $stockActual,
                    now(),
                    'Stock inicial al crear producto'
                );
            }

            // Guardar costos
            if (!empty($validatedData['costos'])) {
                foreach ($validatedData['costos'] as $costo) {
                    CostInput::create([
                        'cantidad'      => $costo['cantidad'],
                        'id_unit'       => $costo['id_unit'],
                        'precio_compra' => $costo['precio_compra'],
                        'precio_venta'  => $costo['precio_venta'],
                        'active'        => $costo['active'],
                        'id_input'      => $input->id,
                    ]);
                }
            }
            // Guardar depósitos
            if (!empty($validatedData['depositos'])) {
                foreach ($validatedData['depositos'] as $deposito) {
                    DepositInput::create([
                        'id_deposit'   => $deposito['id_deposit'],
                        'cantidad'     => $deposito['cantidad'],
                        'stock_minimo' => $deposito['stock_minimo'],
                        'stock_maximo' => $deposito['stock_maximo'],
                        'id_input'     => $input->id,
                    ]);
                }
            }

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Insumo creado exitosamente',
                'data' => $input->load(['costInputs', 'depositInputs'])
            ], 201);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Error al crear el insumo',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function update(Request $request, $id)
    {
        $input = Input::findOrFail($id);

        $validatedData = $request->validate([
            'codigo'            => 'nullable|string|max:100',
            'codigo_interno'    => 'nullable|string|max:100',
            'id_unit'           => 'required|integer|exists:unit_measures,id',
            'id_category'       => 'nullable|integer|exists:categories,id',
            'margen_ganancia'   => 'nullable|numeric',
            'id_supplier'       => 'nullable|integer|exists:suppliers,id',
            'igv'               => 'required|in:0,1',
            'igv_porcentaje'    => 'nullable|numeric',
            'stock'             => 'nullable|numeric',
            'name'              => 'required|string|max:255',
            'costos'            => 'nullable|array',
            'costos.*.id'            => 'nullable|exists:cost_inputs,id',
            'costos.*.cantidad'      => 'required|numeric',
            'costos.*.precio_compra' => 'required|numeric',
            'costos.*.precio_venta'  => 'required|numeric',
            'costos.*.active'        => 'required|in:0,1',
            'costos.*.id_unit'       => 'required|integer|exists:unit_measures,id',
            'depositos'   => 'nullable|array',
            'depositos.*.id'           => 'nullable|exists:deposit_inputs,id',
            'depositos.*.id_deposit'   => 'required|integer|exists:deposits,id',
            'depositos.*.cantidad'     => 'required|numeric',
            'depositos.*.stock_minimo' => 'required|numeric',
            'depositos.*.stock_maximo' => 'required|numeric',
        ]);

        DB::beginTransaction();
        try {
            $stockAnterior = $input->stock ?? 0;
            $stockActual = $validatedData['stock'] ?? 0;
            $diferencia = $stockActual - $stockAnterior;
            
            $input->update($validatedData);

            // Registrar en kardex si hubo cambio de stock
            if ($diferencia != 0) {
                $this->registrarKardexDeposit(
                    $input->id,
                    $diferencia > 0 ? 'entrada' : 'salida',
                    'input_update',
                    $input->id,
                    abs($diferencia),
                    $stockAnterior,
                    $stockActual,
                    now(),
                    'Ajuste manual de stock'
                );
            }

            // Sincronizar costos (elimina todos y vuelve a crear)
            $input->costInputs()->delete();
            if (isset($validatedData['costos'])) {
                foreach ($validatedData['costos'] as $costo) {
                    CostInput::create([
                        'cantidad'      => $costo['cantidad'],
                        'precio_compra' => $costo['precio_compra'],
                        'precio_venta'  => $costo['precio_venta'],
                        'active'        => $costo['active'],
                        'id_unit'       => $costo['id_unit'],
                        'id_input'      => $input->id,
                    ]);
                }
            }
            // Sincronizar depósitos (elimina todos y vuelve a crear)
            $input->depositInputs()->delete();
            if (isset($validatedData['depositos'])) {
                foreach ($validatedData['depositos'] as $deposito) {
                    DepositInput::create([
                        'id_deposit'   => $deposito['id_deposit'],
                        'cantidad'     => $deposito['cantidad'],
                        'stock_minimo' => $deposito['stock_minimo'],
                        'stock_maximo' => $deposito['stock_maximo'],
                        'id_input'     => $input->id,
                    ]);
                }
            }

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => 'Insumo actualizado exitosamente',
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json([
                'success' => false,
                'message' => 'Error al actualizar el insumo',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    public function destroy($id)
    {
        $input = Input::findOrFail($id);
        $input->delete();

        return response()->json([
            'success' => true,
            'message' => 'Insumo eliminado exitosamente'
        ]);
    }

    public function show($id)
    {
        $input = Input::with(['costInputs', 'depositInputs', 'unit', 'category', 'supplier'])->findOrFail($id);

        return response()->json([
            'success' => true,
            'data' => $input
        ]);
    }

    // Listados para selects
    public function getSelectData()
    {
        return response()->json([
            'success' => true,
            'units' => Unit::select('id', 'name_es as name')->orderBy('name_es')->get(),
            'categories' =>  Category::select('id', 'name')->orderBy('name')->get(),
            'suppliers' =>  Supplier::select('id', 'razon_social as name')->orderBy('razon_social')->get(),
            'deposits' =>  Deposit::select('id', 'name')->orderBy('name')->get()
        ]);
    }

    /**
     * Registra un movimiento en el kardex de almacén
     */
    private function registrarKardexDeposit($idProduct, $tipoMovimiento, $documentoTipo, $documentoId, $cantidad, $stockAnterior, $stockActual, $fecha, $observacion = null)
    {
        $depositInput = DepositInput::where('id_input', $idProduct)->first();
        $idDeposit = $depositInput ? $depositInput->id_deposit : 1;

        KardexDeposit::create([
            'id_deposit' => $idDeposit,
            'id_input' => $idProduct,
            'tipo_movimiento' => $tipoMovimiento,
            'documento_tipo' => $documentoTipo,
            'documento_id' => $documentoId,
            'cantidad' => $cantidad,
            'stock_anterior' => $stockAnterior,
            'stock_actual' => $stockActual,
            'fecha' => $fecha,
            'observacion' => $observacion ?? ucfirst($tipoMovimiento) . ' por ' . $documentoTipo,
        ]);
    }
}
