false, 'message' => 'Método no permitido. Use POST']); exit(); } try { $input = json_decode(file_get_contents('php://input'), true); if (!$input) $input = $_POST; if (!isset($input['id'])) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Falta el campo obligatorio: id']); exit(); } $id = (int)$input['id']; // 1) Verificar que la reserva existe $stmt = $pdo->prepare("SELECT id, codigo, estado FROM reservas WHERE id = ?"); $stmt->execute([$id]); $reserva = $stmt->fetch(); if (!$reserva) { http_response_code(404); echo json_encode(['success' => false, 'message' => 'Reserva no encontrada']); exit(); } // 2) Estados en los que se permite editar $estados_editables = ['pendiente_pago', 'confirmada', 'activa']; if (!in_array($reserva['estado'], $estados_editables)) { http_response_code(400); echo json_encode([ 'success' => false, 'message' => "No se puede editar una reserva en estado '{$reserva['estado']}'. Estados permitidos: " . implode(', ', $estados_editables) ]); exit(); } // 3) Construir UPDATE dinámico con los campos recibidos $campos = []; $params = [':id' => $id]; // 📅 Fecha if (isset($input['fecha']) && !empty($input['fecha'])) { $campos[] = "fecha = :fecha"; $params[':fecha'] = $input['fecha']; } // 🕐 Hora inicio if (isset($input['hora_inicio']) && !empty($input['hora_inicio'])) { $campos[] = "hora_inicio = :hora_inicio"; $params[':hora_inicio'] = $input['hora_inicio']; } // 🕐 Hora fin prevista if (isset($input['hora_fin_prevista']) && !empty($input['hora_fin_prevista'])) { $campos[] = "hora_fin_prevista = :hora_fin_prevista"; $params[':hora_fin_prevista'] = $input['hora_fin_prevista']; } // ⏱️ Duración en bloques if (isset($input['duracion_bloques']) && $input['duracion_bloques'] > 0) { $campos[] = "duracion_bloques = :duracion_bloques"; $params[':duracion_bloques'] = (int)$input['duracion_bloques']; } // 💶 Importe if (isset($input['importe']) && $input['importe'] >= 0) { $campos[] = "importe = :importe"; $params[':importe'] = floatval($input['importe']); } // 📊 Estado if (isset($input['estado']) && !empty($input['estado'])) { $estados_validos = ['pendiente_pago', 'pagada_pendiente_aprobacion', 'confirmada', 'activa', 'finalizada', 'cancelada', 'excedida']; if (!in_array($input['estado'], $estados_validos)) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Estado no válido. Válidos: ' . implode(', ', $estados_validos)]); exit(); } $campos[] = "estado = :estado"; $params[':estado'] = $input['estado']; } // 🏠 Cabina if (isset($input['cabina_id']) && !empty($input['cabina_id'])) { $cabina_id = (int)$input['cabina_id']; // Validar que la cabina esté disponible en el nuevo horario $fecha_check = $input['fecha'] ?? null; $hora_inicio_check = $input['hora_inicio'] ?? null; $hora_fin_check = $input['hora_fin_prevista'] ?? null; if ($fecha_check && $hora_inicio_check && $hora_fin_check) { $stmtCheck = $pdo->prepare(" SELECT COUNT(*) FROM reservas WHERE cabina_id = ? AND id != ? AND fecha = ? AND estado IN ('confirmada', 'activa', 'pagada_pendiente_aprobacion') AND (hora_inicio < ? AND hora_fin_prevista > ?) "); $stmtCheck->execute([$cabina_id, $id, $fecha_check, $hora_fin_check, $hora_inicio_check]); if ((int)$stmtCheck->fetchColumn() > 0) { http_response_code(409); echo json_encode(['success' => false, 'message' => 'La cabina seleccionada ya tiene otra reserva en ese horario']); exit(); } } $campos[] = "cabina_id = :cabina_id"; $params[':cabina_id'] = $cabina_id; } // 🐾 Mascota if (isset($input['mascota_id']) && !empty($input['mascota_id'])) { $campos[] = "mascota_id = :mascota_id"; $params[':mascota_id'] = (int)$input['mascota_id']; } // 📝 Notas (campo opcional - si tu tabla no tiene columna 'notas', comenta estas líneas) if (isset($input['notas'])) { try { // Verificar si la columna existe $stmtCol = $pdo->query("SHOW COLUMNS FROM reservas LIKE 'notas'"); if ($stmtCol && $stmtCol->rowCount() > 0) { $campos[] = "notas = :notas"; $params[':notas'] = $input['notas']; } } catch (Exception $e) { // Si no existe la columna, ignorar el campo notas } } if (empty($campos)) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'No se proporcionaron campos a actualizar']); exit(); } // 4) UPDATE $sql = "UPDATE reservas SET " . implode(', ', $campos) . " WHERE id = :id"; $stmt = $pdo->prepare($sql); $stmt->execute($params); // 5) Devolver la reserva actualizada con JOINs $stmtGet = $pdo->prepare(" SELECT r.id, r.codigo, r.fecha, r.hora_inicio, r.hora_fin_prevista, r.duracion_bloques, r.importe, r.estado, r.qr_activo, u.nombre AS cliente_nombre, u.apellidos AS cliente_apellidos, u.email AS cliente_email, m.nombre AS mascota_nombre, m.especie AS mascota_especie, c.codigo AS cabina_codigo, c.bloque FROM reservas r JOIN usuarios u ON r.usuario_id = u.id JOIN mascotas m ON r.mascota_id = m.id JOIN cabinas c ON r.cabina_id = c.id WHERE r.id = ? "); $stmtGet->execute([$id]); echo json_encode([ 'success' => true, 'message' => 'Reserva actualizada correctamente', 'data' => $stmtGet->fetch() ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } catch (PDOException $e) { http_response_code(500); echo json_encode(['success' => false, 'message' => 'Error en el servidor', 'error' => $e->getMessage()]); } ?>