<?php
require_once 'config.php';

header('Content-Type: application/json; charset=utf-8');

$method = $_SERVER['REQUEST_METHOD'];
$accion = $_GET['accion'] ?? '';
$db     = getDB();

// ── FUNCIONES JWT ADMIN ──────────────────────────────────
function generateAdminToken() {
    $header  = base64UrlEncode(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
    $payload = base64UrlEncode(json_encode([
        'admin' => true,
        'iat'   => time(),
        'exp'   => time() + (8 * 3600),
    ]));
    $sig = base64UrlEncode(hash_hmac('sha256', "$header.$payload", ADMIN_SECRET, true));
    return "$header.$payload.$sig";
}

function validarAdmin() {
    $headers = function_exists('getallheaders') ? getallheaders() : [];
    if (empty($headers)) {
        foreach ($_SERVER as $k => $v) {
            if (str_starts_with($k, 'HTTP_')) {
                $key = str_replace('_', '-', ucwords(strtolower(substr($k, 5)), '_'));
                $headers[$key] = $v;
            }
        }
    }
    $auth = $headers['Authorization'] ?? $headers['authorization'] ?? '';
    if (!preg_match('/^Bearer\s+(.+)$/i', trim($auth), $m)) {
        jsonResponse(['error' => 'No autorizado'], 401);
    }
    $parts = explode('.', $m[1]);
    if (count($parts) !== 3) jsonResponse(['error' => 'Token inválido'], 401);
    [$header, $payload, $sig] = $parts;
    $expected = base64UrlEncode(hash_hmac('sha256', "$header.$payload", ADMIN_SECRET, true));
    if (!hash_equals($expected, $sig)) jsonResponse(['error' => 'Firma inválida'], 401);
    $data = json_decode(base64UrlDecode($payload), true);
    if (!$data || empty($data['admin']) || $data['exp'] < time()) {
        jsonResponse(['error' => 'Token expirado'], 401);
    }
}

function getAdminConfig($db, $clave) {
    $stmt = $db->prepare('SELECT valor FROM admin_config WHERE clave = ?');
    $stmt->execute([$clave]);
    return $stmt->fetchColumn();
}

// ── LOGIN ADMIN ──────────────────────────────────────────
if ($accion === 'login' && $method === 'POST') {
    verificarRateLimit($db, 'admin');

    $data = getJsonInput();
    $user = trim($data['usuario'] ?? '');
    $pass = $data['password'] ?? '';

    $adminUser = getAdminConfig($db, 'admin_user');
    $adminHash = getAdminConfig($db, 'admin_pass');

    if ($user !== $adminUser || !password_verify($pass, $adminHash)) {
        registrarIntentoFallido($db, 'admin');
        jsonResponse(['error' => 'Credenciales inválidas'], 401);
    }

    limpiarIntentos($db, 'admin');
    jsonResponse(['token' => generateAdminToken()]);
}

// ── CAMBIAR CONTRASEÑA ADMIN ─────────────────────────────
if ($accion === 'cambiar_password_admin' && $method === 'POST') {
    validarAdmin();
    $data        = getJsonInput();
    $passActual  = $data['password_actual'] ?? '';
    $passNueva   = trim($data['password_nueva'] ?? '');
    $passConfirm = trim($data['password_confirmar'] ?? '');

    $adminHash = getAdminConfig($db, 'admin_pass');

    if (!password_verify($passActual, $adminHash)) {
        jsonResponse(['error' => 'La contraseña actual es incorrecta'], 400);
    }
    if (strlen($passNueva) < 8) {
        jsonResponse(['error' => 'La nueva contraseña debe tener al menos 8 caracteres'], 400);
    }
    if ($passNueva !== $passConfirm) {
        jsonResponse(['error' => 'Las contraseñas no coinciden'], 400);
    }

    $nuevoHash = password_hash($passNueva, PASSWORD_BCRYPT);
    $db->prepare('UPDATE admin_config SET valor = ? WHERE clave = ?')
       ->execute([$nuevoHash, 'admin_pass']);

    jsonResponse(['ok' => true]);
}

// ── LISTAR NEGOCIOS ──────────────────────────────────────
if ($accion === 'listar' && $method === 'GET') {
    validarAdmin();
    $stmt = $db->prepare(
        'SELECT id, nombre, slug, email, categoria, telefono, whatsapp, activo, created_at,
                direccion, descripcion, facebook, instagram, youtube, tiktok, latitud, longitud,
                imagen_portada, tipo_cuenta
         FROM negocios ORDER BY id DESC'
    );
    $stmt->execute();
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    jsonResponse($rows);
}

// ── IMPORTAR TODOS LOS NEGOCIOS DESDE API ────────────────
if ($accion === 'importar_todo' && $method === 'POST') {
    validarAdmin();
    $url = 'https://api.ww-api.com/front/get_items/1548254/23481345/?category_index=0&geoloc=1&per_page=100';
    $ctx = stream_context_create(['http' => ['timeout' => 20, 'user_agent' => 'MSVPortal/1.0']]);
    $json = @file_get_contents($url, false, $ctx);
    if ($json === false) jsonResponse(['error' => 'No se pudo conectar al API externo'], 500);

    $data = json_decode($json, true);
    $lista = null;
    if (isset($data['items']) && is_array($data['items']))    $lista = $data['items'];
    elseif (isset($data['data']) && is_array($data['data'])) $lista = $data['data'];
    elseif (is_array($data) && isset($data[0]))              $lista = $data;
    if ($lista === null) jsonResponse(['error' => 'Formato inesperado del API', 'muestra' => substr($json, 0, 300)], 500);

    $importados = 0;
    $omitidos   = 0;

    foreach ($lista as $item) {
        $nombre   = trim($item['title']       ?? '');
        $telefono = trim($item['phoneNumber'] ?? '');
        $direccion= trim($item['address']     ?? '');
        $latitud  = isset($item['latitude'])  && $item['latitude']  !== '' ? (float)$item['latitude']  : null;
        $longitud = isset($item['longitude']) && $item['longitude'] !== '' ? (float)$item['longitude'] : null;
        $resumen  = strip_tags($item['summary'] ?? '');

        $website  = trim($item['website'] ?? '');
        $facebook = (stripos($website, 'facebook.com') !== false) ? $website : '';

        // Imagen de portada — está al nivel del item, no dentro de images
        $portada = trim($item['originalThumbnail'] ?? $item['largeThumbnail'] ?? '');

        if (!$nombre) { $omitidos++; continue; }

        // Generar slug único
        $base = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '-',
            iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $nombre)
        ), '-'));
        $slug = $base; $i = 2;
        while (true) {
            $st = $db->prepare('SELECT id FROM negocios WHERE slug = ?');
            $st->execute([$slug]);
            if (!$st->fetch()) break;
            // Si ya existe este slug con el mismo nombre, es el mismo negocio — omitir
            $st2 = $db->prepare('SELECT id FROM negocios WHERE slug = ? AND nombre = ?');
            $st2->execute([$slug, $nombre]);
            if ($st2->fetch()) { $slug = null; break; }
            $slug = $base . '-' . $i++;
        }
        if ($slug === null) { $omitidos++; continue; }

        // Imágenes del API — todas van a galería, ninguna como logo
        $imagenes  = isset($item['images']) && is_array($item['images']) ? $item['images'] : [];
        $fotosUrls = [];

        foreach ($imagenes as $idx => $img) {
            // Si ya hay portada, saltar la primera imagen (es la misma foto)
            if ($idx === 0 && $portada !== '') continue;
            $url = $img['otherImagesUrl']['large'] ?? $img['url'] ?? null;
            if ($url) $fotosUrls[] = $url;
        }

        // Email placeholder único para negocios importados sin cuenta
        $emailPlaceholder = 'sin-cuenta-' . $slug . '@import.local';

        try {
            $db->prepare(
                'INSERT INTO negocios
                    (nombre, slug, email, password_hash, categoria, direccion, telefono,
                     descripcion, facebook, latitud, longitud, logo_url, imagen_portada, activo)
                 VALUES (?, ?, ?, \'\', \'\', ?, ?, ?, ?, ?, ?, ?, ?, 1)'
            )->execute([$nombre, $slug, $emailPlaceholder, $direccion, $telefono,
                        $resumen ?: null, $facebook ?: null, $latitud, $longitud,
                        null, $portada ?: null]);

            $negocioId = (int)$db->lastInsertId();

            // Insertar fotos de galería
            foreach ($fotosUrls as $orden => $fotoUrl) {
                $db->prepare(
                    'INSERT INTO fotos (negocio_id, url, orden) VALUES (?, ?, ?)'
                )->execute([$negocioId, $fotoUrl, $orden]);
            }

            $importados++;
        } catch (\Exception $e) {
            $omitidos++;
        }
    }

    jsonResponse(['ok' => true, 'importados' => $importados, 'omitidos' => $omitidos]);
}

// ── CREAR CUENTA A NEGOCIO IMPORTADO ────────────────────
if ($accion === 'crear_cuenta' && $method === 'POST') {
    validarAdmin();
    $id   = (int)($_GET['id'] ?? 0);
    $data = getJsonInput();
    $email    = trim($data['email']    ?? '');
    $password = trim($data['password'] ?? '');

    if (!$id)    jsonResponse(['error' => 'ID requerido'], 400);
    if (!$email) jsonResponse(['error' => 'Email requerido'], 400);
    if (strlen($password) < 8) jsonResponse(['error' => 'Mínimo 8 caracteres'], 400);

    $stmt = $db->prepare('SELECT id FROM negocios WHERE email = ? AND id != ? AND email NOT LIKE \'sin-cuenta-%\'');
    $stmt->execute([$email, $id]);
    if ($stmt->fetch()) jsonResponse(['error' => 'El email ya está en uso'], 409);

    $hash = password_hash($password, PASSWORD_BCRYPT);
    $db->prepare('UPDATE negocios SET email=?, password_hash=? WHERE id=?')
       ->execute([$email, $hash, $id]);

    jsonResponse(['ok' => true]);
}

// ── CREAR NEGOCIO ────────────────────────────────────────
if ($accion === 'crear' && $method === 'POST') {
    validarAdmin();
    $data = getJsonInput();

    $nombre      = trim($data['nombre']      ?? '');
    $email       = trim($data['email']       ?? '');
    $password    = trim($data['password']    ?? '');
    $categoria   = trim($data['categoria']   ?? '');
    $direccion   = trim($data['direccion']   ?? '');
    $telefono    = trim($data['telefono']    ?? '');
    $whatsapp    = trim($data['whatsapp']    ?? '');
    $descripcion = $data['descripcion']      ?? null;
    $facebook    = trim($data['facebook']    ?? '');
    $instagram   = trim($data['instagram']   ?? '');
    $youtube     = trim($data['youtube']     ?? '');
    $tiktok      = trim($data['tiktok']      ?? '');
    $latitud     = isset($data['latitud'])   && $data['latitud'] !== '' ? (float)$data['latitud']  : null;
    $longitud    = isset($data['longitud'])  && $data['longitud'] !== '' ? (float)$data['longitud'] : null;
    $tipo_cuenta = in_array($data['tipo_cuenta'] ?? '', ['negocio','miembro','ambos']) ? $data['tipo_cuenta'] : 'negocio';

    if (!$nombre || !$email || !$password) {
        jsonResponse(['error' => 'nombre, email y password son requeridos'], 400);
    }
    if (strlen($password) < 8) {
        jsonResponse(['error' => 'La contraseña debe tener al menos 8 caracteres'], 400);
    }

    $stmt = $db->prepare('SELECT id FROM negocios WHERE email = ?');
    $stmt->execute([$email]);
    if ($stmt->fetch()) {
        jsonResponse(['error' => 'El email ya está en uso'], 409);
    }

    $base = strtolower(trim(preg_replace('/[^a-z0-9]+/i', '-',
        iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $nombre)
    ), '-'));
    $slug = $base;
    $i    = 2;
    while (true) {
        $st = $db->prepare('SELECT id FROM negocios WHERE slug = ?');
        $st->execute([$slug]);
        if (!$st->fetch()) break;
        $slug = $base . '-' . $i++;
    }

    $hash = password_hash($password, PASSWORD_BCRYPT);
    $stmt = $db->prepare(
        'INSERT INTO negocios
            (nombre, slug, email, password_hash, categoria, direccion, telefono, whatsapp,
             descripcion, facebook, instagram, youtube, tiktok, latitud, longitud, tipo_cuenta, activo)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)'
    );
    $stmt->execute([
        $nombre, $slug, $email, $hash, $categoria, $direccion, $telefono, $whatsapp,
        $descripcion ?: null, $facebook ?: null, $instagram ?: null, $youtube ?: null, $tiktok ?: null,
        $latitud, $longitud, $tipo_cuenta,
    ]);

    jsonResponse(['id' => (int)$db->lastInsertId(), 'slug' => $slug, 'ok' => true], 201);
}

// ── EDITAR NEGOCIO ───────────────────────────────────────
if ($accion === 'editar' && $method === 'POST') {
    validarAdmin();
    $id   = (int)($_GET['id'] ?? 0);
    $data = getJsonInput();

    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $nombre      = trim($data['nombre']      ?? '');
    $email       = trim($data['email']       ?? '');
    $categoria   = trim($data['categoria']   ?? '');
    $direccion   = trim($data['direccion']   ?? '');
    $telefono    = trim($data['telefono']    ?? '');
    $whatsapp    = trim($data['whatsapp']    ?? '');
    $descripcion = $data['descripcion']      ?? null;
    $facebook    = trim($data['facebook']    ?? '');
    $instagram   = trim($data['instagram']   ?? '');
    $youtube     = trim($data['youtube']     ?? '');
    $tiktok      = trim($data['tiktok']      ?? '');
    $latitud     = isset($data['latitud'])   && $data['latitud'] !== '' ? (float)$data['latitud']  : null;
    $longitud    = isset($data['longitud'])  && $data['longitud'] !== '' ? (float)$data['longitud'] : null;
    $tipo_cuenta = in_array($data['tipo_cuenta'] ?? '', ['negocio','miembro','ambos']) ? $data['tipo_cuenta'] : 'negocio';

    if (!$nombre || !$email) jsonResponse(['error' => 'nombre y email son requeridos'], 400);

    $stmt = $db->prepare('SELECT id FROM negocios WHERE email = ? AND id != ?');
    $stmt->execute([$email, $id]);
    if ($stmt->fetch()) jsonResponse(['error' => 'El email ya está en uso'], 409);

    $db->prepare(
        'UPDATE negocios
         SET nombre=?, email=?, categoria=?, direccion=?, telefono=?, whatsapp=?,
             descripcion=?, facebook=?, instagram=?, youtube=?, tiktok=?, latitud=?, longitud=?, tipo_cuenta=?
         WHERE id=?'
    )->execute([
        $nombre, $email, $categoria, $direccion, $telefono, $whatsapp,
        $descripcion ?: null, $facebook ?: null, $instagram ?: null, $youtube ?: null, $tiktok ?: null,
        $latitud, $longitud, $tipo_cuenta, $id,
    ]);

    jsonResponse(['ok' => true]);
}

// ── SUBIR PORTADA (admin) ────────────────────────────────
if ($accion === 'subir_portada' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    if (empty($_FILES['portada']) || $_FILES['portada']['error'] !== UPLOAD_ERR_OK) {
        jsonResponse(['error' => 'No se recibió imagen válida'], 400);
    }
    if ($_FILES['portada']['size'] > MAX_FILE_SIZE) {
        jsonResponse(['error' => 'Imagen demasiado grande (máx. 3 MB)'], 400);
    }

    $stmt = $db->prepare('SELECT imagen_portada FROM negocios WHERE id = ?');
    $stmt->execute([$id]);
    $actual = $stmt->fetchColumn();
    if ($actual && strpos($actual, UPLOAD_URL) !== false) eliminarArchivoUpload($actual);

    $url = comprimirYGuardarImagen($_FILES['portada']['tmp_name'], $id, 'portadas');
    if (!$url) jsonResponse(['error' => 'Formato no válido (solo JPG/PNG)'], 400);

    $db->prepare('UPDATE negocios SET imagen_portada = ? WHERE id = ?')->execute([$url, $id]);
    jsonResponse(['imagen_portada' => $url]);
}

// ── ELIMINAR PORTADA (admin) ─────────────────────────────
if ($accion === 'eliminar_portada' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare('SELECT imagen_portada FROM negocios WHERE id = ?');
    $stmt->execute([$id]);
    $img = $stmt->fetchColumn();
    if ($img && strpos($img, UPLOAD_URL) !== false) eliminarArchivoUpload($img);
    $db->prepare('UPDATE negocios SET imagen_portada = NULL WHERE id = ?')->execute([$id]);
    jsonResponse(['ok' => true]);
}

// ── RESET PASSWORD ───────────────────────────────────────
if ($accion === 'reset_password' && $method === 'POST') {
    validarAdmin();
    $id   = (int)($_GET['id'] ?? 0);
    $data = getJsonInput();
    $pass = trim($data['password'] ?? '');

    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);
    if (strlen($pass) < 8) jsonResponse(['error' => 'Mínimo 8 caracteres'], 400);

    $hash = password_hash($pass, PASSWORD_BCRYPT);
    $db->prepare('UPDATE negocios SET password_hash=? WHERE id=?')->execute([$hash, $id]);

    jsonResponse(['ok' => true]);
}

// ── TOGGLE ACTIVO ────────────────────────────────────────
if ($accion === 'toggle' && $method === 'PATCH') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare('SELECT activo FROM negocios WHERE id = ?');
    $stmt->execute([$id]);
    $neg = $stmt->fetch();
    if (!$neg) jsonResponse(['error' => 'Negocio no encontrado'], 404);

    $nuevo = $neg['activo'] ? 0 : 1;
    $db->prepare('UPDATE negocios SET activo=? WHERE id=?')->execute([$nuevo, $id]);

    jsonResponse(['activo' => $nuevo]);
}

// ── GET NEGOCIO COMPLETO (admin) ─────────────────────────
if ($accion === 'get_negocio' && $method === 'GET') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare(
        'SELECT id, nombre, slug, email, categoria, direccion, telefono, whatsapp,
                descripcion, descripcion_en, facebook, instagram, youtube, tiktok,
                latitud, longitud, logo_url, imagen_portada, activo, es_miembro
         FROM negocios WHERE id = ?'
    );
    $stmt->execute([$id]);
    $neg = $stmt->fetch();
    if (!$neg) jsonResponse(['error' => 'Negocio no encontrado'], 404);
    jsonResponse($neg);
}

// ── GUARDAR INFO COMPLETA (admin) ────────────────────────
if ($accion === 'guardar_info' && $method === 'POST') {
    validarAdmin();
    $id   = (int)($_GET['id'] ?? 0);
    $data = getJsonInput();
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $nombre         = trim($data['nombre']         ?? '');
    $email          = trim($data['email']          ?? '');
    $categoria      = trim($data['categoria']      ?? '');
    $direccion      = trim($data['direccion']      ?? '');
    $telefono       = trim($data['telefono']       ?? '');
    $whatsapp       = trim($data['whatsapp']       ?? '');
    $descripcion    = $data['descripcion']         ?? null;
    $descripcion_en = $data['descripcion_en']      ?? null;
    $facebook       = trim($data['facebook']       ?? '');
    $instagram      = trim($data['instagram']      ?? '');
    $youtube        = trim($data['youtube']        ?? '');
    $tiktok         = trim($data['tiktok']         ?? '');
    $latitud        = isset($data['latitud'])  && $data['latitud']  !== '' ? (float)$data['latitud']  : null;
    $longitud       = isset($data['longitud']) && $data['longitud'] !== '' ? (float)$data['longitud'] : null;
    $es_miembro     = isset($data['es_miembro']) ? (int)(bool)$data['es_miembro'] : null;

    if (!$nombre || !$email) jsonResponse(['error' => 'nombre y email son requeridos'], 400);

    $stmt = $db->prepare('SELECT id FROM negocios WHERE email = ? AND id != ?');
    $stmt->execute([$email, $id]);
    if ($stmt->fetch()) jsonResponse(['error' => 'El email ya está en uso'], 409);

    $miembroSQL = $es_miembro !== null ? ', es_miembro=?' : '';
    $params = [
        $nombre, $email, $categoria, $direccion, $telefono, $whatsapp,
        $descripcion ?: null, $descripcion_en ?: null,
        $facebook ?: null, $instagram ?: null, $youtube ?: null, $tiktok ?: null,
        $latitud, $longitud,
    ];
    if ($es_miembro !== null) $params[] = $es_miembro;
    $params[] = $id;

    $db->prepare(
        "UPDATE negocios
         SET nombre=?, email=?, categoria=?, direccion=?, telefono=?, whatsapp=?,
             descripcion=?, descripcion_en=?, facebook=?, instagram=?, youtube=?, tiktok=?,
             latitud=?, longitud=?{$miembroSQL}
         WHERE id=?"
    )->execute($params);

    jsonResponse(['ok' => true]);
}

// ── SUBIR LOGO (admin) ───────────────────────────────────
if ($accion === 'subir_logo' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    if (empty($_FILES['logo']) || $_FILES['logo']['error'] !== UPLOAD_ERR_OK)
        jsonResponse(['error' => 'No se recibió imagen válida'], 400);
    if ($_FILES['logo']['size'] > MAX_FILE_SIZE)
        jsonResponse(['error' => 'Imagen demasiado grande (máx. 3 MB)'], 400);

    $stmt = $db->prepare('SELECT logo_url FROM negocios WHERE id = ?');
    $stmt->execute([$id]);
    $actual = $stmt->fetchColumn();
    if ($actual) eliminarArchivoUpload($actual);

    $url = comprimirYGuardarImagen($_FILES['logo']['tmp_name'], $id, 'logos');
    if (!$url) jsonResponse(['error' => 'Formato no válido (solo JPG/PNG)'], 400);

    $db->prepare('UPDATE negocios SET logo_url = ? WHERE id = ?')->execute([$url, $id]);
    jsonResponse(['logo_url' => $url]);
}

// ── ELIMINAR LOGO (admin) ────────────────────────────────
if ($accion === 'eliminar_logo' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare('SELECT logo_url FROM negocios WHERE id = ?');
    $stmt->execute([$id]);
    $logo = $stmt->fetchColumn();
    if ($logo) eliminarArchivoUpload($logo);
    $db->prepare('UPDATE negocios SET logo_url = NULL WHERE id = ?')->execute([$id]);
    jsonResponse(['ok' => true]);
}

// ── LISTAR FOTOS (admin) ─────────────────────────────────
if ($accion === 'listar_fotos' && $method === 'GET') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare('SELECT id, url, orden FROM fotos WHERE negocio_id = ? ORDER BY orden ASC, id ASC');
    $stmt->execute([$id]);
    jsonResponse($stmt->fetchAll());
}

// ── SUBIR FOTO (admin) ───────────────────────────────────
if ($accion === 'subir_foto' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    if (empty($_FILES['foto']) || $_FILES['foto']['error'] !== UPLOAD_ERR_OK)
        jsonResponse(['error' => 'No se recibió imagen válida'], 400);
    if ($_FILES['foto']['size'] > MAX_FILE_SIZE)
        jsonResponse(['error' => 'Imagen demasiado grande (máx. 3 MB)'], 400);

    $url = comprimirYGuardarImagen($_FILES['foto']['tmp_name'], $id, 'fotos');
    if (!$url) jsonResponse(['error' => 'Formato no válido (solo JPG/PNG)'], 400);

    $stmt = $db->prepare('SELECT COALESCE(MAX(orden),0)+1 FROM fotos WHERE negocio_id = ?');
    $stmt->execute([$id]);
    $orden = (int)$stmt->fetchColumn();

    $db->prepare('INSERT INTO fotos (negocio_id, url, orden) VALUES (?, ?, ?)')->execute([$id, $url, $orden]);
    jsonResponse(['id' => (int)$db->lastInsertId(), 'url' => $url, 'orden' => $orden], 201);
}

// ── REORDENAR FOTOS (admin) ──────────────────────────────
if ($accion === 'reordenar_fotos' && $method === 'POST') {
    validarAdmin();
    $data = getJsonInput();
    $ids  = $data['ids'] ?? [];
    if (!is_array($ids) || !count($ids)) jsonResponse(['error' => 'ids requerido'], 400);
    $stmt = $db->prepare('UPDATE fotos SET orden = ? WHERE id = ?');
    foreach ($ids as $orden => $fotoId) {
        $stmt->execute([$orden, (int)$fotoId]);
    }
    jsonResponse(['ok' => true]);
}

// ── ELIMINAR FOTO (admin) ────────────────────────────────
if ($accion === 'eliminar_foto' && $method === 'POST') {
    validarAdmin();
    $foto_id = (int)($_GET['foto_id'] ?? 0);
    if (!$foto_id) jsonResponse(['error' => 'foto_id requerido'], 400);

    $stmt = $db->prepare('SELECT url FROM fotos WHERE id = ?');
    $stmt->execute([$foto_id]);
    $foto = $stmt->fetch();
    if (!$foto) jsonResponse(['error' => 'Foto no encontrada'], 404);

    eliminarArchivoUpload($foto['url']);
    $db->prepare('DELETE FROM fotos WHERE id = ?')->execute([$foto_id]);
    jsonResponse(['ok' => true]);
}

// ── GET HORARIOS (admin) ─────────────────────────────────
if ($accion === 'get_horarios' && $method === 'GET') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare(
        'SELECT dia_semana, hora_apertura, hora_cierre, cerrado
         FROM horarios WHERE negocio_id = ? ORDER BY dia_semana ASC'
    );
    $stmt->execute([$id]);
    jsonResponse($stmt->fetchAll());
}

// ── GUARDAR HORARIOS (admin) ─────────────────────────────
if ($accion === 'guardar_horarios' && $method === 'POST') {
    validarAdmin();
    $id   = (int)($_GET['id'] ?? 0);
    $data = getJsonInput();
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);
    if (!isset($data['horarios']) || !is_array($data['horarios']))
        jsonResponse(['error' => 'Array horarios requerido'], 400);

    $stmt = $db->prepare(
        'INSERT INTO horarios (negocio_id, dia_semana, hora_apertura, hora_cierre, cerrado)
         VALUES (?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE hora_apertura=VALUES(hora_apertura),
                                 hora_cierre=VALUES(hora_cierre),
                                 cerrado=VALUES(cerrado)'
    );
    foreach ($data['horarios'] as $h) {
        $dia     = (int)($h['dia_semana']   ?? 0);
        $abre    = $h['hora_apertura'] ?? null;
        $cierra  = $h['hora_cierre']   ?? null;
        $cerrado = $h['cerrado']       ? 1 : 0;
        $stmt->execute([$id, $dia, $cerrado ? null : $abre, $cerrado ? null : $cierra, $cerrado]);
    }
    jsonResponse(['ok' => true]);
}

// ── LISTAR PROMOCIONES (admin) ───────────────────────────
if ($accion === 'listar_promos' && $method === 'GET') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare('SELECT * FROM promociones WHERE negocio_id = ? ORDER BY fecha_inicio DESC');
    $stmt->execute([$id]);
    jsonResponse($stmt->fetchAll());
}

// ── CREAR PROMO (admin) ──────────────────────────────────
if ($accion === 'crear_promo' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $titulo      = trim($_POST['titulo']      ?? '');
    $descripcion = trim($_POST['descripcion'] ?? '');
    $f_inicio    = $_POST['fecha_inicio'] ?? '';
    $f_fin       = $_POST['fecha_fin']    ?? '';

    if (!$titulo || !$f_inicio || !$f_fin)
        jsonResponse(['error' => 'titulo, fecha_inicio y fecha_fin son requeridos'], 400);
    if ($f_fin < $f_inicio)
        jsonResponse(['error' => 'fecha_fin no puede ser anterior a fecha_inicio'], 400);

    $imagen_url = null;
    if (!empty($_FILES['imagen']) && $_FILES['imagen']['error'] === UPLOAD_ERR_OK) {
        if ($_FILES['imagen']['size'] > MAX_FILE_SIZE) jsonResponse(['error' => 'Imagen demasiado grande'], 400);
        $imagen_url = comprimirYGuardarImagen($_FILES['imagen']['tmp_name'], $id, 'promos');
        if (!$imagen_url) jsonResponse(['error' => 'Formato de imagen no válido'], 400);
    }

    $db->prepare(
        'INSERT INTO promociones (negocio_id, titulo, descripcion, imagen_url, fecha_inicio, fecha_fin)
         VALUES (?, ?, ?, ?, ?, ?)'
    )->execute([$id, $titulo, $descripcion ?: null, $imagen_url, $f_inicio, $f_fin]);

    jsonResponse(['id' => (int)$db->lastInsertId()], 201);
}

// ── EDITAR PROMO (admin) ─────────────────────────────────
if ($accion === 'editar_promo' && $method === 'POST') {
    validarAdmin();
    $promo_id = (int)($_GET['promo_id'] ?? 0);
    if (!$promo_id) jsonResponse(['error' => 'promo_id requerido'], 400);

    $titulo      = trim($_POST['titulo']      ?? '');
    $descripcion = trim($_POST['descripcion'] ?? '');
    $f_inicio    = $_POST['fecha_inicio'] ?? '';
    $f_fin       = $_POST['fecha_fin']    ?? '';

    if (!$titulo || !$f_inicio || !$f_fin)
        jsonResponse(['error' => 'titulo, fecha_inicio y fecha_fin son requeridos'], 400);
    if ($f_fin < $f_inicio)
        jsonResponse(['error' => 'fecha_fin no puede ser anterior a fecha_inicio'], 400);

    $stmt = $db->prepare('SELECT imagen_url FROM promociones WHERE id = ?');
    $stmt->execute([$promo_id]);
    $promo = $stmt->fetch();
    if (!$promo) jsonResponse(['error' => 'Promoción no encontrada'], 404);

    $imagen_url = $promo['imagen_url'];
    if (!empty($_FILES['imagen']) && $_FILES['imagen']['error'] === UPLOAD_ERR_OK) {
        if ($_FILES['imagen']['size'] > MAX_FILE_SIZE) jsonResponse(['error' => 'Imagen demasiado grande'], 400);
        $nueva = comprimirYGuardarImagen($_FILES['imagen']['tmp_name'], $promo_id, 'promos');
        if (!$nueva) jsonResponse(['error' => 'Formato de imagen no válido'], 400);
        eliminarArchivoUpload($imagen_url);
        $imagen_url = $nueva;
    }

    $db->prepare(
        'UPDATE promociones SET titulo=?, descripcion=?, imagen_url=?, fecha_inicio=?, fecha_fin=? WHERE id=?'
    )->execute([$titulo, $descripcion ?: null, $imagen_url, $f_inicio, $f_fin, $promo_id]);

    jsonResponse(['ok' => true]);
}

// ── TOGGLE PROMO (admin) ─────────────────────────────────
if ($accion === 'toggle_promo' && $method === 'POST') {
    validarAdmin();
    $promo_id = (int)($_GET['promo_id'] ?? 0);
    if (!$promo_id) jsonResponse(['error' => 'promo_id requerido'], 400);

    $stmt = $db->prepare('SELECT activo FROM promociones WHERE id = ?');
    $stmt->execute([$promo_id]);
    $promo = $stmt->fetch();
    if (!$promo) jsonResponse(['error' => 'Promoción no encontrada'], 404);

    $nuevo = $promo['activo'] ? 0 : 1;
    $db->prepare('UPDATE promociones SET activo=? WHERE id=?')->execute([$nuevo, $promo_id]);
    jsonResponse(['activo' => $nuevo]);
}

// ── ELIMINAR PROMO (admin) ───────────────────────────────
if ($accion === 'eliminar_promo' && $method === 'POST') {
    validarAdmin();
    $promo_id = (int)($_GET['promo_id'] ?? 0);
    if (!$promo_id) jsonResponse(['error' => 'promo_id requerido'], 400);

    $stmt = $db->prepare('SELECT imagen_url FROM promociones WHERE id = ?');
    $stmt->execute([$promo_id]);
    $promo = $stmt->fetch();
    if (!$promo) jsonResponse(['error' => 'Promoción no encontrada'], 404);

    eliminarArchivoUpload($promo['imagen_url']);
    $db->prepare('DELETE FROM promociones WHERE id = ?')->execute([$promo_id]);
    jsonResponse(['ok' => true]);
}

// ── LISTAR BANNERS (admin) ───────────────────────────────
if ($accion === 'listar_banners' && $method === 'GET') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $stmt = $db->prepare('SELECT * FROM banners WHERE negocio_id = ? ORDER BY fecha_inicio DESC');
    $stmt->execute([$id]);
    jsonResponse($stmt->fetchAll());
}

// ── SUBIR BANNER (admin) ─────────────────────────────────
if ($accion === 'subir_banner' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);

    $link_destino = trim($_POST['link_destino'] ?? '');
    $f_inicio     = $_POST['fecha_inicio'] ?? '';
    $f_fin        = $_POST['fecha_fin']    ?? '';

    if (!$f_inicio || !$f_fin) jsonResponse(['error' => 'fecha_inicio y fecha_fin son requeridos'], 400);
    if ($f_fin < $f_inicio)    jsonResponse(['error' => 'fecha_fin no puede ser anterior a fecha_inicio'], 400);
    if (empty($_FILES['imagen']) || $_FILES['imagen']['error'] !== UPLOAD_ERR_OK)
        jsonResponse(['error' => 'La imagen del banner es requerida'], 400);
    if ($_FILES['imagen']['size'] > MAX_FILE_SIZE) jsonResponse(['error' => 'Imagen demasiado grande'], 400);

    $imagen_url = comprimirYGuardarImagen($_FILES['imagen']['tmp_name'], $id, 'banners');
    if (!$imagen_url) jsonResponse(['error' => 'Formato de imagen no válido'], 400);

    $db->prepare(
        'INSERT INTO banners (negocio_id, imagen_url, link_destino, fecha_inicio, fecha_fin) VALUES (?, ?, ?, ?, ?)'
    )->execute([$id, $imagen_url, $link_destino ?: null, $f_inicio, $f_fin]);

    jsonResponse(['id' => (int)$db->lastInsertId()], 201);
}

// ── ELIMINAR BANNER (admin) ──────────────────────────────
if ($accion === 'eliminar_banner' && $method === 'POST') {
    validarAdmin();
    $banner_id = (int)($_GET['banner_id'] ?? 0);
    if (!$banner_id) jsonResponse(['error' => 'banner_id requerido'], 400);

    $stmt = $db->prepare('SELECT imagen_url FROM banners WHERE id = ?');
    $stmt->execute([$banner_id]);
    $banner = $stmt->fetch();
    if (!$banner) jsonResponse(['error' => 'Banner no encontrado'], 404);

    eliminarArchivoUpload($banner['imagen_url']);
    $db->prepare('DELETE FROM banners WHERE id = ?')->execute([$banner_id]);
    jsonResponse(['ok' => true]);
}

// ── LISTAR KEYWORDS (admin) ──────────────────────────────
if ($accion === 'listar_keywords' && $method === 'GET') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);
    $stmt = $db->prepare('SELECT id, keyword FROM keywords WHERE negocio_id = ? ORDER BY id ASC');
    $stmt->execute([$id]);
    jsonResponse($stmt->fetchAll());
}

// ── AGREGAR KEYWORD (admin) ──────────────────────────────
if ($accion === 'agregar_keyword' && $method === 'POST') {
    validarAdmin();
    $id   = (int)($_GET['id'] ?? 0);
    $data = getJsonInput();
    $keyword = trim(strtolower($data['keyword'] ?? ''));
    if (!$id)      jsonResponse(['error' => 'ID requerido'], 400);
    if (!$keyword) jsonResponse(['error' => 'Keyword vacía'], 400);
    if (strlen($keyword) > 60) jsonResponse(['error' => 'Máximo 60 caracteres'], 400);

    $stmt = $db->prepare('SELECT COUNT(*) FROM keywords WHERE negocio_id = ?');
    $stmt->execute([$id]);
    if ((int)$stmt->fetchColumn() >= 50)
        jsonResponse(['error' => 'Límite de 50 keywords alcanzado'], 400);

    try {
        $db->prepare('INSERT INTO keywords (negocio_id, keyword) VALUES (?, ?)')->execute([$id, $keyword]);
        jsonResponse(['id' => (int)$db->lastInsertId(), 'keyword' => $keyword], 201);
    } catch (\Exception $e) {
        jsonResponse(['error' => 'Esa keyword ya existe'], 409);
    }
}

// ── ELIMINAR KEYWORD (admin) ─────────────────────────────
if ($accion === 'eliminar_keyword' && $method === 'POST') {
    validarAdmin();
    $kw_id = (int)($_GET['kw_id'] ?? 0);
    if (!$kw_id) jsonResponse(['error' => 'kw_id requerido'], 400);
    $db->prepare('DELETE FROM keywords WHERE id = ?')->execute([$kw_id]);
    jsonResponse(['ok' => true]);
}

// ── ELIMINAR CUENTA (negocio o miembro) ─────────────────
if ($accion === 'eliminar_cuenta' && $method === 'POST') {
    validarAdmin();
    $id = (int)($_GET['id'] ?? 0);
    if (!$id) jsonResponse(['error' => 'ID requerido'], 400);
    // Eliminar archivos asociados
    $stmt = $db->prepare('SELECT logo_url, imagen_portada FROM negocios WHERE id = ?');
    $stmt->execute([$id]);
    $neg = $stmt->fetch();
    if (!$neg) jsonResponse(['error' => 'No encontrado'], 404);
    if ($neg['logo_url'])       eliminarArchivoUpload($neg['logo_url']);
    if ($neg['imagen_portada']) eliminarArchivoUpload($neg['imagen_portada']);
    // Eliminar fotos
    $fotos = $db->prepare('SELECT url FROM fotos WHERE negocio_id = ?');
    $fotos->execute([$id]);
    foreach ($fotos->fetchAll() as $f) eliminarArchivoUpload($f['url']);
    // Eliminar el negocio (cascade elimina tablas relacionadas si FK ON DELETE CASCADE)
    $db->prepare('DELETE FROM fotos       WHERE negocio_id = ?')->execute([$id]);
    $db->prepare('DELETE FROM horarios    WHERE negocio_id = ?')->execute([$id]);
    $db->prepare('DELETE FROM promociones WHERE negocio_id = ?')->execute([$id]);
    $db->prepare('DELETE FROM banners     WHERE negocio_id = ?')->execute([$id]);
    $db->prepare('DELETE FROM keywords    WHERE negocio_id = ?')->execute([$id]);
    $db->prepare('DELETE FROM negocios    WHERE id = ?')->execute([$id]);
    jsonResponse(['ok' => true]);
}

jsonResponse(['error' => 'Acción no válida'], 400);
