export const prerender = false;

import type { APIRoute } from 'astro';
import { env } from 'cloudflare:workers';
import { sql } from 'drizzle-orm';
import { buildAuthEngine, type AuthEnv } from '../../../lib/auth-engine.js';
import { getDb, type DbEnv } from '../../../lib/db.js';
import {
  getSession,
  invalidateAllSessionsForUser,
  setSession,
  type SessionEnv,
} from '../../../lib/session.js';
import { type StorefrontLimiterEnv } from '../../../lib/rate-limit.js';

type ProfileEnv = AuthEnv & SessionEnv & DbEnv & StorefrontLimiterEnv;

function normalizeExecuteRows(result: unknown): unknown[] {
  if (Array.isArray(result)) return result;
  const rows = (result as { rows?: unknown[] } | null)?.rows;
  return rows ?? [];
}

export const POST: APIRoute = async ({ request, cookies, redirect }) => {
  const cfEnv = env as ProfileEnv | undefined;

  const session = cfEnv ? await getSession(cfEnv, cookies) : null;
  if (!session) {
    return redirect('/login', 302);
  }

  if (!cfEnv?.SESSION || (!cfEnv?.DB && !cfEnv?.DATABASE_URL)) {
    return redirect('/account/settings?error=service_unavailable', 302);
  }

  const formData = await request.formData();
  const email = String(formData.get('email') ?? '').trim().toLowerCase();
  const currentPassword = String(formData.get('currentPassword') ?? '');
  const newPassword = String(formData.get('newPassword') ?? '');
  const confirmPassword = String(formData.get('confirmPassword') ?? '');

  if (email && email !== session.email.toLowerCase()) {
    return redirect('/account/settings?error=email_change_not_supported', 302);
  }

  const wantsPasswordChange =
    currentPassword.length > 0 || newPassword.length > 0 || confirmPassword.length > 0;

  if (!wantsPasswordChange) {
    return redirect('/account/settings?saved=1', 302);
  }

  if (!currentPassword) {
    return redirect('/account/settings?error=missing_current_password', 302);
  }

  if (newPassword.length < 8 || newPassword !== confirmPassword) {
    return redirect('/account/settings?error=weak_password', 302);
  }

  const { db } = getDb(cfEnv);
  const res = await db.execute(sql`
    SELECT password_hash FROM auth_users WHERE id = ${session.userId} LIMIT 1
  `);
  const rows = normalizeExecuteRows(res);
  const row = rows[0] as { password_hash?: unknown } | undefined;
  const storedHash = typeof row?.password_hash === 'string' ? row.password_hash : null;

  if (!storedHash) {
    return redirect('/account/settings?error=invalid_credentials', 302);
  }

  const auth = buildAuthEngine(cfEnv);
  const currentOk = await auth.verifyPassword(currentPassword, storedHash);
  if (!currentOk) {
    return redirect('/account/settings?error=invalid_credentials', 302);
  }

  await auth.setPassword(session.userId, newPassword);
  await db.execute(sql`
    UPDATE auth_users SET password_changed_at = NOW() WHERE id = ${session.userId}
  `);

  await invalidateAllSessionsForUser(cfEnv, session.userId);
  await setSession(cfEnv, cookies, session);

  return redirect('/account/settings?saved=1', 302);
};
