<?php
require_once __DIR__ . '/../config/database.php';
require_once __DIR__ . '/../includes/helpers.php';

$pdo = getConnection();
$action = $_GET['action'] ?? '';
$method = $_SERVER['REQUEST_METHOD'];

try {
    switch ($action) {

        // ─── Listar Órdenes de Compra ───────────────────────────
        case 'listar':
            $sucursal_id = intval($_GET['sucursal_id'] ?? 0);
            $estado = $_GET['estado'] ?? '';
            $proveedor_id = intval($_GET['proveedor_id'] ?? 0);
            $desde = $_GET['desde'] ?? '';
            $hasta = $_GET['hasta'] ?? '';
            $offset = intval($_GET['offset'] ?? 0);
            $limit = min(100, max(1, intval($_GET['limit'] ?? 50)));

            $where = [];
            $params = [];
            if ($sucursal_id) { $where[] = 'o.sucursal_id=?'; $params[]=$sucursal_id; }
            if ($estado) { $where[] = 'o.estado=?'; $params[]=$estado; }
            if ($proveedor_id) { $where[] = 'o.proveedor_id=?'; $params[]=$proveedor_id; }
            if ($desde) { $where[] = 'o.fecha_emision>=?'; $params[]=$desde; }
            if ($hasta) { $where[] = 'o.fecha_emision<=?'; $params[]=$hasta; }
            $whereSQL = $where ? 'WHERE ' . implode(' AND ', $where) : '';

            // Total
            $c = $pdo->prepare("SELECT COUNT(*) FROM ordenes_compra o $whereSQL");
            $c->execute($params);
            $total = intval($c->fetchColumn());

            // Rows
            $s = $pdo->prepare("SELECT o.*, p.nombre as proveedor, s.nombre as sucursal,
                    COALESCE((SELECT COUNT(*) FROM ordenes_compra_detalle WHERE orden_compra_id=o.id),0) as lineas,
                    TIMESTAMPDIFF(DAY, o.fecha_emision, NOW()) as dias_desde_emision
                FROM ordenes_compra o
                JOIN lugarcompra p ON p.id=o.proveedor_id
                JOIN sucursales s ON s.id=o.sucursal_id
                $whereSQL
                ORDER BY o.fecha_emision DESC, o.id DESC
                LIMIT $limit OFFSET $offset");
            $s->execute($params);
            json_success([
                'rows' => $s->fetchAll(),
                'total' => $total,
                'offset' => $offset,
                'limit' => $limit
            ]);
            break;

        // ─── Ver una OC con detalle ────────────────────────────
        case 'ver':
            $id = intval($_GET['id'] ?? 0);
            if (!$id) json_error('ID requerido');

            $s = $pdo->prepare("SELECT o.*, p.nombre as proveedor, p.telefono as proveedor_tel,
                    p.dias_credito, p.dias_entrega, s.nombre as sucursal,
                    u.nombre as usuario_creador
                FROM ordenes_compra o
                JOIN lugarcompra p ON p.id=o.proveedor_id
                JOIN sucursales s ON s.id=o.sucursal_id
                LEFT JOIN usuarios u ON u.id=o.usuario_creador_id
                WHERE o.id=?");
            $s->execute([$id]);
            $oc = $s->fetch();
            if (!$oc) json_error('OC no encontrada', 404);

            $d = $pdo->prepare("SELECT d.*, pr.NombreComercial as producto, pr.CodigoInterno as codigo,
                    pr.CodigoBarra as barra, pz.nombre as presentacion
                FROM ordenes_compra_detalle d
                JOIN productos pr ON pr.id=d.producto_id
                LEFT JOIN presentaciones pz ON pz.id=d.presentacion_id
                WHERE d.orden_compra_id=?
                ORDER BY d.id");
            $d->execute([$id]);
            $oc['detalle'] = $d->fetchAll();

            json_success($oc);
            break;

        // ─── Crear OC ──────────────────────────────────────────
        case 'crear':
            require_post();
            $data = json_input();
            require_fields($data, ['proveedor_id', 'sucursal_id', 'detalle']);

            $proveedor_id = intval($data['proveedor_id']);
            $sucursal_id = intval($data['sucursal_id']);
            $detalle = $data['detalle'];
            if (!is_array($detalle) || count($detalle) === 0) json_error('Debe incluir al menos 1 producto');

            $pdo->beginTransaction();
            try {
                // Generar numero_oc
                $year = date('Ymd');
                $r = $pdo->query("SELECT COUNT(*) FROM ordenes_compra WHERE DATE(fecha_emision)=CURDATE()");
                $seq = intval($r->fetchColumn()) + 1;
                $numero_oc = "OC-$year-" . str_pad($seq, 4, '0', STR_PAD_LEFT);

                $fecha_entrega = $data['fecha_entrega_esperada'] ?? null;
                $notas = $data['notas'] ?? '';
                $usuario_id = intval($data['usuario_creador_id'] ?? 0);

                $total = 0;
                $subtotal = 0;
                foreach ($detalle as $item) {
                    $cant = intval($item['cantidad'] ?? 1);
                    $costo = floatval($item['costo_unitario'] ?? 0);
                    $subtotal += $cant * $costo;
                }
                $descuento = floatval($data['descuento'] ?? 0);
                $tasa_impuesto = floatval($data['tasa_impuesto'] ?? 0);
                $impuesto = ($subtotal - $descuento) * $tasa_impuesto / 100;
                $total = $subtotal - $descuento + $impuesto;

                $s = $pdo->prepare("INSERT INTO ordenes_compra
                    (numero_oc, proveedor_id, sucursal_id, fecha_emision, fecha_entrega_esperada,
                     estado, subtotal, descuento, impuesto, total, notas, usuario_creador_id)
                    VALUES (?,?,?, CURDATE(), ?, 'pendiente',?,?,?,?,?,?)");
                $s->execute([
                    $numero_oc, $proveedor_id, $sucursal_id, $fecha_entrega,
                    $subtotal, $descuento, $impuesto, $total, $notas, $usuario_id
                ]);
                $oc_id = intval($pdo->lastInsertId());

                $sd = $pdo->prepare("INSERT INTO ordenes_compra_detalle
                    (orden_compra_id, producto_id, presentacion_id, cantidad_solicitada,
                     costo_unitario_estimado, costo_total_estimado, notas_linea)
                    VALUES (?,?,?,?,?,?,?)");
                foreach ($detalle as $item) {
                    $cant = intval($item['cantidad'] ?? 1);
                    $costo = floatval($item['costo_unitario'] ?? 0);
                    $sd->execute([
                        $oc_id,
                        intval($item['producto_id']),
                        intval($item['presentacion_id'] ?? 0) ?: null,
                        $cant,
                        $costo,
                        $cant * $costo,
                        $item['notas_linea'] ?? ''
                    ]);
                }

                $pdo->commit();
                json_success(['id' => $oc_id, 'numero_oc' => $numero_oc], 'OC creada exitosamente');
            } catch (Exception $e) {
                $pdo->rollBack();
                throw $e;
            }
            break;

        // ─── Editar OC (solo pendiente) ────────────────────────
        case 'editar':
            require_post();
            $data = json_input();
            require_fields($data, ['id']);

            $id = intval($data['id']);
            $s = $pdo->prepare("SELECT estado FROM ordenes_compra WHERE id=?");
            $s->execute([$id]);
            $oc = $s->fetch();
            if (!$oc) json_error('OC no encontrada', 404);
            if ($oc['estado'] !== 'pendiente') json_error('Solo se puede editar OC en estado pendiente');

            $pdo->beginTransaction();
            try {
                $detalle = $data['detalle'] ?? null;
                $notas = $data['notas'] ?? null;
                $fecha_entrega = $data['fecha_entrega_esperada'] ?? null;

                $updates = [];
                $params = [];
                if ($notas !== null) { $updates[] = 'notas=?'; $params[]=$notas; }
                if ($fecha_entrega !== null) { $updates[] = 'fecha_entrega_esperada=?'; $params[]=$fecha_entrega; }

                if (is_array($detalle) && count($detalle) > 0) {
                    // Recalcular totales
                    $subtotal = 0;
                    foreach ($detalle as $item) {
                        $cant = intval($item['cantidad'] ?? 1);
                        $costo = floatval($item['costo_unitario'] ?? 0);
                        $subtotal += $cant * $costo;
                    }
                    $descuento = floatval($data['descuento'] ?? 0);
                    $tasa_impuesto = floatval($data['tasa_impuesto'] ?? 0);
                    $impuesto = ($subtotal - $descuento) * $tasa_impuesto / 100;
                    $total = $subtotal - $descuento + $impuesto;

                    $updates[] = 'subtotal=?'; $params[]=$subtotal;
                    $updates[] = 'descuento=?'; $params[]=$descuento;
                    $updates[] = 'impuesto=?'; $params[]=$impuesto;
                    $updates[] = 'total=?'; $params[]=$total;

                    // Reemplazar detalle
                    $pdo->prepare("DELETE FROM ordenes_compra_detalle WHERE orden_compra_id=?")->execute([$id]);
                    $sd = $pdo->prepare("INSERT INTO ordenes_compra_detalle
                        (orden_compra_id, producto_id, presentacion_id, cantidad_solicitada,
                         costo_unitario_estimado, costo_total_estimado, notas_linea)
                        VALUES (?,?,?,?,?,?,?)");
                    foreach ($detalle as $item) {
                        $cant = intval($item['cantidad'] ?? 1);
                        $costo = floatval($item['costo_unitario'] ?? 0);
                        $sd->execute([
                            $id,
                            intval($item['producto_id']),
                            intval($item['presentacion_id'] ?? 0) ?: null,
                            $cant, $costo, $cant * $costo,
                            $item['notas_linea'] ?? ''
                        ]);
                    }
                }

                if (count($updates) > 0) {
                    $updates[] = 'updated_at=NOW()';
                    $sql = "UPDATE ordenes_compra SET " . implode(',', $updates) . " WHERE id=?";
                    $params[] = $id;
                    $pdo->prepare($sql)->execute($params);
                }

                $pdo->commit();
                json_success(['id' => $id], 'OC actualizada');
            } catch (Exception $e) {
                $pdo->rollBack();
                throw $e;
            }
            break;

        // ─── Cambiar estado ────────────────────────────────────
        case 'cambiar_estado':
            require_post();
            $data = json_input();
            require_fields($data, ['id', 'estado']);

            $id = intval($data['id']);
            $nuevo_estado = $data['estado'];
            $estados_validos = ['pendiente','aprobada','enviada','recibida_parcial','completada','cancelada'];
            if (!in_array($nuevo_estado, $estados_validos)) json_error('Estado invalido');

            $s = $pdo->prepare("SELECT estado FROM ordenes_compra WHERE id=?");
            $s->execute([$id]);
            $oc = $s->fetch();
            if (!$oc) json_error('OC no encontrada', 404);

            // Validar transiciones
            $actual = $oc['estado'];
            $transiciones = [
                'pendiente' => ['aprobada','cancelada'],
                'aprobada' => ['enviada','cancelada'],
                'enviada' => ['recibida_parcial','completada','cancelada'],
                'recibida_parcial' => ['completada','cancelada'],
            ];
            if ($nuevo_estado !== $actual && !in_array($nuevo_estado, $transiciones[$actual] ?? [])) {
                json_error("No se puede pasar de $actual a $nuevo_estado");
            }

            $pdo->prepare("UPDATE ordenes_compra SET estado=?, updated_at=NOW() WHERE id=?")
                ->execute([$nuevo_estado, $id]);

            json_success(['id' => $id, 'estado' => $nuevo_estado], "OC $nuevo_estado");
            break;

        // ─── Eliminar OC (solo pendiente) ──────────────────────
        case 'eliminar':
            require_post();
            $data = json_input();
            require_fields($data, ['id']);

            $id = intval($data['id']);
            $s = $pdo->prepare("SELECT estado FROM ordenes_compra WHERE id=?");
            $s->execute([$id]);
            $oc = $s->fetch();
            if (!$oc) json_error('OC no encontrada', 404);
            if ($oc['estado'] !== 'pendiente') json_error('Solo se puede eliminar OC en estado pendiente');

            $pdo->prepare("DELETE FROM ordenes_compra WHERE id=?")->execute([$id]);
            json_success([], 'OC eliminada');
            break;

        // ─── Productos por proveedor ──────────────────────────
        case 'productos_proveedor':
            $prov = intval($_GET['proveedor_id'] ?? 0);
            if (!$prov) json_error('Proveedor requerido');

            $s = $pdo->prepare("SELECT p.id, p.CodigoInterno as codigo, p.CodigoBarra as barra,
                    p.NombreComercial as producto, p.laboratorio,
                    COALESCE(w.costo_promedio_unidad_base, 0) as ultimo_costo,
                    COALESCE((SELECT stock_total FROM inventario_sucursal WHERE producto_id=p.id ORDER BY stock_total DESC LIMIT 1), 0) as stock_actual,
                    pp.id as presentacion_id, pz.nombre as presentacion, pp.factor_conversion
                FROM producto_lugares_compra plc
                JOIN productos p ON p.id=plc.producto_id AND p.estado=1
                JOIN producto_presentaciones pp ON pp.producto_id=p.id AND pp.activo=1 AND pp.es_comprable=1
                JOIN presentaciones pz ON pz.id=pp.presentacion_id
                LEFT JOIN productos_costo_promedio w ON w.producto_id=p.id
                WHERE plc.lugar_compra_id=? AND plc.activo=1
                ORDER BY p.NombreComercial");
            $s->execute([$prov]);

            // Also get supplier name
            $provName = $pdo->prepare("SELECT nombre, dias_entrega FROM lugarcompra WHERE id=?");
            $provName->execute([$prov]);
            $proveedorInfo = $provName->fetch();

            json_success([
                'proveedor' => $proveedorInfo,
                'productos' => $s->fetchAll()
            ]);
            break;

        // ─── Proveedores activos ──────────────────────────────
        case 'proveedores':
            $s = $pdo->query("SELECT id, nombre, telefono, email, dias_credito, dias_entrega
                FROM lugarcompra WHERE activo=1 OR activo IS NULL ORDER BY nombre");
            json_success($s->fetchAll());
            break;

        // ─── Sucursales ────────────────────────────────────────
        case 'sucursales':
            $s = $pdo->query("SELECT id, nombre FROM sucursales ORDER BY nombre");
            json_success($s->fetchAll());
            break;

        // ─── Convertir OC en Compra ───────────────────────────
        case 'convertir_compra':
            require_post();
            $data = json_input();
            require_fields($data, ['id']);

            $id = intval($data['id']);
            $s = $pdo->prepare("SELECT o.*, p.nombre as proveedor
                FROM ordenes_compra o
                JOIN lugarcompra p ON p.id=o.proveedor_id
                WHERE o.id=? AND o.estado IN ('aprobada','enviada','recibida_parcial')");
            $s->execute([$id]);
            $oc = $s->fetch();
            if (!$oc) json_error('OC no encontrada o no esta en estado aprobado/enviado');

            $detalle = $pdo->prepare("SELECT d.*, pr.CodigoInterno, pr.NombreComercial
                FROM ordenes_compra_detalle d
                JOIN productos pr ON pr.id=d.producto_id
                WHERE d.orden_compra_id=?");
            $detalle->execute([$id]);
            $items = $detalle->fetchAll();
            if (count($items) === 0) json_error('La OC no tiene productos');

            $pdo->beginTransaction();
            try {
                // Insert compra
                $total = floatval($data['total'] ?? $oc['total']);
                $tipo_pago = $data['tipo_pago'] ?? 'credito';
                $fecha_compra = $data['fecha_compra'] ?? date('Y-m-d H:i:s');
                $facturado = intval($data['facturado'] ?? 0);
                $numero_factura = $data['numero_factura'] ?? '';

                $sc = $pdo->prepare("INSERT INTO compras (fecha_compra, id_lugarCompra, total, tipo_pago, estado_pago)
                    VALUES (?,?,?,?,'pendiente')");
                $sc->execute([$fecha_compra, $oc['proveedor_id'], $total, $tipo_pago]);
                $compra_id = intval($pdo->lastInsertId());

                // Insert detalle
                $sd = $pdo->prepare("INSERT INTO compras_detalle
                    (compra_id, producto_id, cantidad, presentacion_id, costo_unitario, costo_total,
                     facturado, numero_factura, fecha_vencimiento, cantidad_unidades_base, factor_conversion_compra)
                    VALUES (?,?,?,?,?,?,?,?,?,?,?)");

                // Update inventario
                $upd = $pdo->prepare("INSERT INTO inventario_sucursal (producto_id, sucursal_id, stock_total, stock_facturado, stock_no_facturado, costo_promedio_local)
                    VALUES (?,?,?,?,?,?)
                    ON DUPLICATE KEY UPDATE stock_total=stock_total+VALUES(stock_total),
                        stock_facturado=stock_facturado+VALUES(stock_facturado),
                        stock_no_facturado=stock_no_facturado+VALUES(stock_no_facturado),
                        costo_promedio_local=VALUES(costo_promedio_local)");

                // Kardex
                $km = $pdo->prepare("INSERT INTO inventario_movimientos
                    (producto_id, sucursal_id, tipo_movimiento, cantidad, saldo_despues, referencia_id, justificacion)
                    VALUES (?,?,'ingreso_compra',?,?,?,?)");

                foreach ($items as $item) {
                    $cant = intval($data['cantidades'][$item['id']] ?? $item['cantidad_solicitada']);
                    $costo = floatval($data['costos'][$item['id']] ?? $item['costo_unitario_estimado']);
                    $vencimiento = $data['vencimientos'][$item['id']] ?? null;
                    $presentacion_id = $item['presentacion_id'];

                    // Get conversion factor
                    $fcf = 1;
                    if ($presentacion_id) {
                        $st = $pdo->prepare("SELECT factor_conversion FROM producto_presentaciones WHERE producto_id=? AND presentacion_id=?");
                        $st->execute([$item['producto_id'], $presentacion_id]);
                        $pcf = $st->fetch();
                        $fcf = $pcf ? intval($pcf['factor_conversion']) : 1;
                    }
                    $unidades_base = $cant * $fcf;

                    $sd->execute([
                        $compra_id, $item['producto_id'], $cant, $presentacion_id,
                        $costo, $cant * $costo,
                        $facturado, $numero_factura ?: null, $vencimiento,
                        $unidades_base, $fcf
                    ]);

                    // Stock update
                    $upd->execute([
                        $item['producto_id'], $oc['sucursal_id'],
                        $unidades_base,
                        $facturado ? $unidades_base : 0,
                        $facturado ? 0 : $unidades_base,
                        $costo / $fcf
                    ]);

                    // WAC update
                    $pdo->exec("INSERT INTO productos_costo_promedio (producto_id, costo_promedio_unidad_base, cantidad_total_unidades, valor_total_inventario)
                        VALUES ({$item['producto_id']}, $costo, $unidades_base, {$cant} * $costo)
                        ON DUPLICATE KEY UPDATE
                            costo_promedio_unidad_base = (costo_promedio_unidad_base * cantidad_total_unidades + VALUES(costo_promedio_unidad_base) * VALUES(cantidad_total_unidades)) / (cantidad_total_unidades + VALUES(cantidad_total_unidades)),
                            cantidad_total_unidades = cantidad_total_unidades + VALUES(cantidad_total_unidades),
                            valor_total_inventario = valor_total_inventario + VALUES(valor_total_inventario)");

                    // Get final stock
                    $st2 = $pdo->prepare("SELECT stock_total FROM inventario_sucursal WHERE producto_id=? AND sucursal_id=?");
                    $st2->execute([$item['producto_id'], $oc['sucursal_id']]);
                    $final_stock = intval($st2->fetchColumn());

                    $justificacion_kardex = "Conversion OC #{$oc['numero_oc']} (" . ($facturado ? 'Facturado' : 'Sin Factura') . ")";
                    $km->execute([
                        $item['producto_id'], $oc['sucursal_id'],
                        $unidades_base, $final_stock, "OC-{$oc['numero_oc']}",
                        $justificacion_kardex
                    ]);
                }

                // Marcar OC como completada y vincular
                $pdo->prepare("UPDATE ordenes_compra SET estado='completada', compra_id=?, updated_at=NOW() WHERE id=?")
                    ->execute([$compra_id, $id]);

                // Cuenta por pagar si es credito
                if ($tipo_pago === 'credito' || $tipo_pago === 'mixto') {
                    $fecha_limite = date('Y-m-d', strtotime("+{$oc['dias_credito']} days"));
                    $pdo->prepare("INSERT INTO cuentas_pagar (compra_id, proveedor_id, fecha_compra, fecha_vencimiento, total_factura, saldo_pendiente, estado, dias_credito)
                        VALUES (?,?,?,?,?,?,'pendiente',?)")
                        ->execute([$compra_id, $oc['proveedor_id'], date('Y-m-d'), $fecha_limite, $total, $total, $oc['dias_credito']]);
                }

                $pdo->commit();
                json_success(['compra_id' => $compra_id, 'oc_id' => $id], 'Compra creada desde OC');
            } catch (Exception $e) {
                $pdo->rollBack();
                throw $e;
            }
            break;

        default:
            json_error('Accion no valida');
    }
} catch (Exception $e) {
    json_error('Error: '.$e->getMessage());
}
