import type { RequestHandler } from './$types';
import { redirect } from '@sveltejs/kit';
import { getDb } from '$lib/server/db';
import { sha256Hex, randomTokenBase64Url } from '$lib/server/crypto';
import { sessionIdleTtlMs, isProd, isDev, DEV_BYPASS_AUTH } from '$lib/server/env';
import { toIsoSqlUTC } from '$lib/server/datetime';


function escapeHtml(s: string): string {
	return s
		.replaceAll('&', '&amp;')
		.replaceAll('<', '&lt;')
		.replaceAll('>', '&gt;')
		.replaceAll('"', '&quot;')
		.replaceAll("'", '&#39;');
}

// GET: página intermedia que requiere una interacción mínima y establece una cookie "login_intent" vía JS.
// Evita que bots de previsualización canjeen el token antes de que el usuario haga clic.
export const GET: RequestHandler = async (event) => {
	if (isDev() && DEV_BYPASS_AUTH) {
		throw redirect(303, '/app');
	}
	const token = event.url.searchParams.get('token')?.trim();
	if (!token) {
		console.warn('[web/login] Solicitud sin token');
		return new Response('Falta el token', { status: 400 });
	}

	// Nonce para "gate de JS"
	const nonce = randomTokenBase64Url(18);

	const html = `<!doctype html>
<html lang="es">
  <head>
    <meta charset="utf-8" />
		<meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>Acceder</title>
    <meta name="robots" content="noindex,nofollow" />
    <meta name="referrer" content="no-referrer" />
    <meta name="color-scheme" content="light dark" />
    <style>
      :root { color-scheme: light dark; }
      body {
        font-family: sans-serif;
        padding: 2rem;
        background: #ffffff;
        color: #111111;
      }
      .card {
        max-width: 480px;
        margin: 0 auto;
        border: 1px solid #dddddd;
        border-radius: 8px;
        padding: 1.5rem;
        background: #ffffff;
      }
      button[disabled] { opacity: .6; cursor: not-allowed; }
      @media (prefers-color-scheme: dark) {
        body { background: #0b0b0b; color: #eeeeee; }
        .card { border-color: #333333; background: #161616; }
      }
    </style>
  </head>
  <body>
    <div class="card">
      <h1>Acceso a las tareas</h1>
      <p>Pulsa “Continuar”. Si no funciona, copia y pega el enlace en tu navegador.</p>
      <form method="POST" action="/login">
        <input type="hidden" name="token" value="${escapeHtml(token)}" />
        <input type="hidden" id="nonceInput" name="nonce" value="${escapeHtml(nonce)}" />
        <button id="continueBtn" type="submit" disabled>Continuar</button>
      </form>
      <noscript>
        <p><strong>JavaScript está deshabilitado.</strong> Actívalo para continuar.</p>
      </noscript>
    </div>
    <script>
      // Establecer cookie de intención con el nonce y habilitar el botón.
      try {
        var nonce = ${JSON.stringify(nonce)};
        var cookie = 'login_intent=' + encodeURIComponent(nonce) + '; Path=/; Max-Age=600; SameSite=Lax';
        if (location.protocol === 'https:') cookie += '; Secure';
        document.cookie = cookie;
        var btn = document.getElementById('continueBtn');
        if (btn) btn.removeAttribute('disabled');
      } catch {}
    </script>
  </body>
</html>`;

	return new Response(html, {
		status: 200,
		headers: {
			'content-type': 'text/html; charset=utf-8',
			'cache-control': 'no-store, max-age=0'
		}
	});
};

// POST: canje real del token (uso único). Crea sesión y redirige a /app.
export const POST: RequestHandler = async (event) => {
	if (isDev() && DEV_BYPASS_AUTH) {
		throw redirect(303, '/app');
	}
	const form = await event.request.formData();
	const token = String(form.get('token') || '').trim();
	if (!token) {
		console.warn('[web/login] POST sin token');
		return new Response('Falta el token', { status: 400 });
	}

	// Validación del "gate de JS": cookie + nonce deben coincidir
	const nonce = String(form.get('nonce') || '').trim();
	const loginIntent = event.cookies.get('login_intent') || '';
	if (!nonce || !loginIntent || nonce !== loginIntent) {
		console.warn('[web/login] Falta o no cuadra login_intent; posible previsualizador sin JS.');
		return new Response('Solicitud inválida', { status: 400 });
	}

	const tokenHash = await sha256Hex(token);
	const db = await getDb();

	// Intentar canjear el token (un solo uso, no caducado)
	const res = db
		.prepare(
			`UPDATE web_tokens
       SET used_at = strftime('%Y-%m-%d %H:%M:%f','now')
       WHERE token_hash = ?
         AND used_at IS NULL
         AND expires_at > strftime('%Y-%m-%d %H:%M:%f','now')`
		)
		.run(tokenHash);

	const changes = Number(res?.changes || 0);
	if (changes < 1) {
		console.warn('[web/login] Token no canjeado (0 cambios). Posible caducado/ya usado/no existe.');
		return new Response('Enlace inválido o caducado', { status: 400 });
	}

	// Recuperar el user_id asociado
	const row = db
		.prepare(`SELECT user_id FROM web_tokens WHERE token_hash = ?`)
		.get(tokenHash) as { user_id: string } | null;

	const userId = row?.user_id?.trim();
	if (!userId) {
		return new Response('Token canjeado pero usuario no encontrado', { status: 500 });
	}

	// Crear sesión
	const sessionToken = randomTokenBase64Url(32);
	const sessionHash = await sha256Hex(sessionToken);
	const sessionId = randomTokenBase64Url(16);
	const expiresAtIso = toIsoSqlUTC(new Date(Date.now() + sessionIdleTtlMs));

	// Datos de agente e IP (best-effort)
	const userAgent = event.request.headers.get('user-agent') || null;
	let ip: string | null = null;
	try {
		// SvelteKit 2: getClientAddress en adapters compatibles
		// @ts-ignore
		if (typeof event.getClientAddress === 'function') {
			// @ts-ignore
			ip = event.getClientAddress() || null;
		}
	} catch { }
	if (!ip) {
		const fwd = event.request.headers.get('x-forwarded-for');
		ip = fwd ? fwd.split(',')[0].trim() : null;
	}

	db.prepare(
		`INSERT INTO web_sessions (id, user_id, session_hash, expires_at, user_agent, ip)
     VALUES (?, ?, ?, ?, ?, ?)`
	).run(sessionId, userId, sessionHash, expiresAtIso, userAgent, ip);

	// Cookie de sesión
	event.cookies.set('sid', sessionToken, {
		path: '/',
		httpOnly: true,
		sameSite: 'lax',
		secure: isProd(),
		maxAge: Math.floor(sessionIdleTtlMs / 1000)
	});

	// Eliminar cookie de intento (ya no es necesaria)
	event.cookies.delete('login_intent', { path: '/' });

	// Redirigir a /app
	throw redirect(303, '/app');
};
