/**
 * Consumer auth API route handlers for Next.js App Router.
 *
 * Usage in a customer site:
 *   // app/api/consumer/[action]/route.ts
 *   import { NextResponse } from 'next/server';
 *   import { createConsumerAuthHandlers } from 'keystone-design-bootstrap/next/routes/consumer-auth';
 *   export const { POST } = createConsumerAuthHandlers({ NextResponse });
 *
 * Handles: initiate, login, signup, logout
 *
 * Env (server-side only):
 * - API_URL (default: http://localhost:3000/api/v1)
 * - API_KEY
 */

import { CONSUMER_TOKEN_COOKIE } from '../../lib/consumer-session';
import { clientContextHeaders } from './proxy-headers';

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type NextResponseLike = { json: (body: unknown, init?: ResponseInit) => any };

const COOKIE_MAX_AGE = 60 * 60 * 24 * 30; // 30 days

function getApiUrl(): string {
  return process.env.API_URL || 'http://localhost:3000/api/v1';
}

function getApiKey(): string {
  return process.env.API_KEY || '';
}

function apiHeaders(request?: Request): Record<string, string> {
  const key = getApiKey();
  return {
    'Content-Type': 'application/json',
    ...(key ? { 'X-API-Key': key } : {}),
    ...(request ? clientContextHeaders(request) : {}),
  };
}

// POST /api/consumer/initiate
// Looks up an existing user by email or phone, creating a Contact if needed.
// Returns { exists, firstName, hasPassword }.
async function handleInitiate(request: Request, NR: NextResponseLike): Promise<Response> {
  const body = await request.json().catch(() => ({})) as Record<string, unknown>;
  const { email, phone } = body;

  if (!email && !phone) {
    return NR.json({ exists: null });
  }

  try {
    const res = await fetch(`${getApiUrl()}/consumer/auth/initiate`, {
      method: 'POST',
      headers: apiHeaders(request),
      body: JSON.stringify({ email: email || undefined, phone: phone || undefined }),
    });

    if (res.status === 404) return NR.json({ exists: false });
    if (!res.ok) return NR.json({ exists: null });

    const json = await res.json().catch(() => ({}));
    const data = json.data as Record<string, unknown> | undefined;
    return NR.json({
      exists: true,
      firstName: data?.first_name ?? undefined,
      hasPassword: data?.has_password != null ? Boolean(data.has_password) : true,
    });
  } catch {
    return NR.json({ exists: null });
  }
}

// POST /api/consumer/login
// Authenticates an existing user. Sets HttpOnly JWT cookie on success.
// Returns {} on success or { error, code } on failure.
async function handleLogin(request: Request, NR: NextResponseLike): Promise<Response> {
  const body = await request.json().catch(() => ({})) as Record<string, string>;
  const { email, phone, password } = body;

  if (!email && !phone) return NR.json({ error: 'Email or phone is required.' }, { status: 422 });
  if (!password) return NR.json({ error: 'Password is required.' }, { status: 422 });

  const res = await fetch(`${getApiUrl()}/consumer/auth/login`, {
    method: 'POST',
    headers: apiHeaders(request),
    body: JSON.stringify({ email: email || undefined, phone: phone || undefined, password }),
  });

  const json = await res.json().catch(() => ({}));
  if (!res.ok) {
    return NR.json(
      { error: json.error || 'Login failed. Please try again.', code: json.code },
      { status: res.status }
    );
  }

  const token = json.data?.token;
  if (!token) return NR.json({ error: 'No token received.' }, { status: 500 });

  const response = NR.json({});
  response.cookies.set(CONSUMER_TOKEN_COOKIE, token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    path: '/',
    maxAge: COOKIE_MAX_AGE,
  });
  return response;
}

// POST /api/consumer/signup
// Creates a new account (or claims an existing contact). Sets HttpOnly JWT cookie on success.
// Returns {} on success or { error } on failure.
async function handleSignup(request: Request, NR: NextResponseLike): Promise<Response> {
  const body = await request.json().catch(() => ({})) as Record<string, string>;
  const { email, phone, password, password_confirmation, first_name, last_name } = body;

  if (!email && !phone) return NR.json({ error: 'Email or phone is required.' }, { status: 422 });

  const res = await fetch(`${getApiUrl()}/consumer/auth/signup`, {
    method: 'POST',
    headers: apiHeaders(request),
    body: JSON.stringify({
      email: email || undefined,
      phone: phone || undefined,
      password,
      password_confirmation,
      first_name: first_name || undefined,
      last_name: last_name || undefined,
    }),
  });

  const json = await res.json().catch(() => ({}));
  if (!res.ok) {
    return NR.json({ error: json.error || 'Signup failed. Please try again.' }, { status: res.status });
  }

  const token = json.data?.token;
  if (!token) return NR.json({ error: 'No token received.' }, { status: 500 });

  const response = NR.json({ claimed: json.data?.claimed ?? false });
  response.cookies.set(CONSUMER_TOKEN_COOKIE, token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    path: '/',
    maxAge: COOKIE_MAX_AGE,
  });
  return response;
}

// POST /api/consumer/logout
// Clears the JWT cookie.
async function handleLogout(_request: Request, NR: NextResponseLike): Promise<Response> {
  const response = NR.json({ success: true });
  response.cookies.delete(CONSUMER_TOKEN_COOKIE);
  return response;
}

/**
 * Creates a single POST handler that routes to the correct auth action based on
 * the dynamic `[action]` path segment.
 */
export function createConsumerAuthHandlers({ NextResponse }: { NextResponse: NextResponseLike }) {
  return {
    POST: async (
      request: Request,
      context: { params: Promise<{ action: string }> }
    ): Promise<Response> => {
      const { action } = await context.params;
      if (action === 'initiate') return handleInitiate(request, NextResponse);
      if (action === 'login') return handleLogin(request, NextResponse);
      if (action === 'signup') return handleSignup(request, NextResponse);
      if (action === 'logout') return handleLogout(request, NextResponse);
      return NextResponse.json({ error: 'Not found' }, { status: 404 });
    },
  };
}
