import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
import { resolve } from 'node:path';
import { homedir } from 'node:os';

const SESSION_DIR = resolve(homedir(), '.mosaic');
const SESSION_FILE = resolve(SESSION_DIR, 'session.json');

interface StoredSession {
  gatewayUrl: string;
  cookie: string;
  userId: string;
  email: string;
  expiresAt: string;
}

export interface AuthResult {
  cookie: string;
  userId: string;
  email: string;
}

/**
 * Sign in to the gateway and return the session cookie.
 */
export async function signIn(
  gatewayUrl: string,
  email: string,
  password: string,
): Promise<AuthResult> {
  const res = await fetch(`${gatewayUrl}/api/auth/sign-in/email`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', Origin: gatewayUrl },
    body: JSON.stringify({ email, password }),
    redirect: 'manual',
  });

  if (!res.ok) {
    const body = await res.text().catch(() => '');
    throw new Error(`Sign-in failed (${res.status}): ${body}`);
  }

  // Extract set-cookie header
  const setCookieHeader = res.headers.getSetCookie?.() ?? [];
  const sessionCookie = setCookieHeader
    .map((c) => c.split(';')[0]!)
    .filter((c) => c.startsWith('better-auth.session_token='))
    .join('; ');

  if (!sessionCookie) {
    throw new Error('No session cookie returned from sign-in');
  }

  // Parse the response body for user info
  const data = (await res.json()) as { user?: { id: string; email: string } };
  const userId = data.user?.id ?? 'unknown';
  const userEmail = data.user?.email ?? email;

  return { cookie: sessionCookie, userId, email: userEmail };
}

/**
 * Save session to ~/.mosaic/session.json
 */
export function saveSession(gatewayUrl: string, auth: AuthResult): void {
  if (!existsSync(SESSION_DIR)) {
    mkdirSync(SESSION_DIR, { recursive: true });
  }

  const session: StoredSession = {
    gatewayUrl,
    cookie: auth.cookie,
    userId: auth.userId,
    email: auth.email,
    expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), // 7 days
  };

  // 0o600: owner read/write only — the session cookie is a credential
  writeFileSync(SESSION_FILE, JSON.stringify(session, null, 2), { encoding: 'utf-8', mode: 0o600 });
}

/**
 * Load a saved session. Returns null if no session, expired, or wrong gateway.
 */
export function loadSession(gatewayUrl: string): AuthResult | null {
  if (!existsSync(SESSION_FILE)) return null;

  try {
    const raw = readFileSync(SESSION_FILE, 'utf-8');
    const session = JSON.parse(raw) as StoredSession;

    if (session.gatewayUrl !== gatewayUrl) return null;
    if (new Date(session.expiresAt) < new Date()) return null;

    return {
      cookie: session.cookie,
      userId: session.userId,
      email: session.email,
    };
  } catch {
    return null;
  }
}

/**
 * Validate that a stored session is still active by hitting get-session.
 */
export async function validateSession(gatewayUrl: string, cookie: string): Promise<boolean> {
  try {
    const res = await fetch(`${gatewayUrl}/api/auth/get-session`, {
      headers: { Cookie: cookie, Origin: gatewayUrl },
    });
    return res.ok;
  } catch {
    return false;
  }
}
