export type AuthPlatform = "firm" | "client";

const DEMO_EMAIL = "admin@gmail.com";
const DEMO_PASSWORD = "Thetitan@1234";
const DEMO_NAME = "Sara";
const API_BASE = import.meta.env.VITE_API_URL ?? "/api";
const SESSION_EVENT = "amanah-auth-changed";

function apiErrorMessage(data: { detail?: unknown }, fallback: string): string {
  const detail = data.detail;
  if (typeof detail === "string") return detail;
  if (Array.isArray(detail) && detail[0]?.msg) return String(detail[0].msg);
  return fallback;
}

export interface AuthSession {
  email: string;
  name: string;
  company?: string;
  platform: AuthPlatform;
  /** Absolute or API-relative URL for profile photo */
  avatarUrl?: string;
  /** Ledger client ID for client portal users */
  clientId?: string;
}

export interface SignupInput {
  name: string;
  email: string;
  password: string;
  company?: string;
}

export type AuthResult = { ok: true } | { ok: false; error: string };

interface ApiUser {
  email: string;
  name: string;
  company?: string | null;
  platform: string;
  avatar_url?: string | null;
  client_id?: string | null;
}

function storageKey(platform: AuthPlatform) {
  return `abdelouhab-auth-${platform}`;
}

function notifySessionChange(platform: AuthPlatform) {
  if (typeof window === "undefined") return;
  window.dispatchEvent(new CustomEvent(SESSION_EVENT, { detail: { platform } }));
}

/** Resolve avatar URL for <img src>. */
export function resolveAvatarUrl(url?: string | null): string | undefined {
  if (!url) return undefined;
  if (url.startsWith("http://") || url.startsWith("https://") || url.startsWith("blob:")) {
    return url;
  }
  if (url.startsWith("/api/")) return url;
  if (url.startsWith("/")) return `${API_BASE}${url.replace(/^\/api/, "")}`.replace("/api/api", "/api");
  return url;
}

function setSession(
  platform: AuthPlatform,
  user: { email: string; name: string; company?: string; avatarUrl?: string | null; clientId?: string | null },
) {
  localStorage.setItem(storageKey(platform), "true");
  localStorage.setItem(`${storageKey(platform)}-email`, user.email);
  localStorage.setItem(`${storageKey(platform)}-name`, user.name);
  if (user.company) {
    localStorage.setItem(`${storageKey(platform)}-company`, user.company);
  } else {
    localStorage.removeItem(`${storageKey(platform)}-company`);
  }
  if (user.avatarUrl) {
    localStorage.setItem(`${storageKey(platform)}-avatar`, user.avatarUrl);
  } else {
    localStorage.removeItem(`${storageKey(platform)}-avatar`);
  }
  if (user.clientId) {
    localStorage.setItem(`${storageKey(platform)}-client-id`, user.clientId);
  } else {
    localStorage.removeItem(`${storageKey(platform)}-client-id`);
  }
  notifySessionChange(platform);
}

export function isAuthenticated(platform: AuthPlatform): boolean {
  if (typeof window === "undefined") return false;
  return localStorage.getItem(storageKey(platform)) === "true";
}

export function getSession(platform: AuthPlatform): AuthSession | null {
  if (!isAuthenticated(platform)) return null;
  const email = localStorage.getItem(`${storageKey(platform)}-email`) ?? DEMO_EMAIL;
  const name = localStorage.getItem(`${storageKey(platform)}-name`) ?? DEMO_NAME;
  const company = localStorage.getItem(`${storageKey(platform)}-company`) ?? undefined;
  const avatarUrl = localStorage.getItem(`${storageKey(platform)}-avatar`) ?? undefined;
  const clientId = localStorage.getItem(`${storageKey(platform)}-client-id`) ?? undefined;
  return { email, name, company, platform, avatarUrl, clientId };
}

/** Subscribe to session updates (avatar/name changes) without full page reload. */
export function subscribeSession(
  platform: AuthPlatform,
  listener: () => void,
): () => void {
  if (typeof window === "undefined") return () => undefined;
  const handler = (e: Event) => {
    const detail = (e as CustomEvent<{ platform?: AuthPlatform }>).detail;
    if (!detail?.platform || detail.platform === platform) listener();
  };
  window.addEventListener(SESSION_EVENT, handler);
  window.addEventListener("storage", handler);
  return () => {
    window.removeEventListener(SESSION_EVENT, handler);
    window.removeEventListener("storage", handler);
  };
}

export async function login(
  platform: AuthPlatform,
  email: string,
  password: string,
): Promise<boolean> {
  try {
    const response = await fetch(`${API_BASE}/auth/login`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        platform,
        email: email.trim().toLowerCase(),
        password,
      }),
    });
    if (!response.ok) return false;
    const user = (await response.json()) as ApiUser;
    setSession(platform, {
      email: user.email,
      name: user.name,
      company: user.company ?? undefined,
      avatarUrl: user.avatar_url ?? undefined,
      clientId: user.client_id ?? undefined,
    });
    return true;
  } catch {
    const normalized = email.trim().toLowerCase();
    if (normalized === DEMO_EMAIL && password === DEMO_PASSWORD) {
      setSession(platform, { email: normalized, name: DEMO_NAME });
      return true;
    }
    return false;
  }
}

export async function signup(platform: AuthPlatform, input: SignupInput): Promise<AuthResult> {
  const name = input.name.trim();
  const email = input.email.trim().toLowerCase();
  const password = input.password;
  const company = input.company?.trim() || undefined;

  if (!name) return { ok: false, error: "Please enter your name" };
  if (!email || !email.includes("@")) return { ok: false, error: "Please enter a valid email" };
  if (password.length < 8) return { ok: false, error: "Password must be at least 8 characters" };

  try {
    const response = await fetch(`${API_BASE}/auth/signup`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ platform, name, email, password, company }),
    });
    const data = (await response.json().catch(() => ({}))) as ApiUser & { detail?: unknown };
    if (!response.ok) {
      return { ok: false, error: apiErrorMessage(data, "Could not create account") };
    }
    setSession(platform, {
      email: data.email,
      name: data.name,
      company: data.company ?? undefined,
      avatarUrl: data.avatar_url ?? undefined,
      clientId: data.client_id ?? undefined,
    });
    return { ok: true };
  } catch {
    return { ok: false, error: "Could not reach the server. Make sure the API is running." };
  }
}

export function logout(platform: AuthPlatform): void {
  localStorage.removeItem(storageKey(platform));
  localStorage.removeItem(`${storageKey(platform)}-email`);
  localStorage.removeItem(`${storageKey(platform)}-name`);
  localStorage.removeItem(`${storageKey(platform)}-company`);
  localStorage.removeItem(`${storageKey(platform)}-avatar`);
  localStorage.removeItem(`${storageKey(platform)}-client-id`);
  notifySessionChange(platform);
}

export async function updateProfile(
  platform: AuthPlatform,
  input: { name: string; company?: string },
): Promise<AuthResult> {
  const session = getSession(platform);
  if (!session) return { ok: false, error: "You must be signed in" };
  const name = input.name.trim();
  if (!name) return { ok: false, error: "Please enter your name" };

  try {
    const response = await fetch(`${API_BASE}/auth/profile`, {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        platform,
        email: session.email,
        name,
        company: input.company?.trim() || null,
      }),
    });
    const data = (await response.json().catch(() => ({}))) as ApiUser & { detail?: unknown };
    if (!response.ok) {
      return { ok: false, error: apiErrorMessage(data, "Could not update profile") };
    }
    setSession(platform, {
      email: data.email,
      name: data.name,
      company: data.company ?? undefined,
      avatarUrl: data.avatar_url ?? session.avatarUrl,
      clientId: data.client_id ?? session.clientId,
    });
    return { ok: true };
  } catch {
    return { ok: false, error: "Could not reach the server. Make sure the API is running." };
  }
}

/** Keep firm/client sessions in sync when the same email updates their photo. */
function syncAvatarAcrossPlatforms(
  sourcePlatform: AuthPlatform,
  email: string,
  avatarUrl: string | null | undefined,
) {
  const other: AuthPlatform = sourcePlatform === "firm" ? "client" : "firm";
  const otherSession = getSession(other);
  if (!otherSession || otherSession.email.toLowerCase() !== email.toLowerCase()) return;
  setSession(other, {
    email: otherSession.email,
    name: otherSession.name,
    company: otherSession.company,
    avatarUrl: avatarUrl ?? null,
    clientId: otherSession.clientId,
  });
}

export async function uploadAvatar(platform: AuthPlatform, file: File): Promise<AuthResult> {
  const session = getSession(platform);
  if (!session) return { ok: false, error: "You must be signed in" };

  const allowed = ["image/jpeg", "image/jpg", "image/png", "image/webp"];
  if (!allowed.includes(file.type)) {
    return { ok: false, error: "Please upload a JPG, PNG, or WEBP image" };
  }
  if (file.size > 5 * 1024 * 1024) {
    return { ok: false, error: "Image must be 5 MB or smaller" };
  }

  const body = new FormData();
  body.append("platform", platform);
  body.append("email", session.email);
  body.append("file", file);

  try {
    const response = await fetch(`${API_BASE}/auth/avatar`, {
      method: "POST",
      body,
    });
    const data = (await response.json().catch(() => ({}))) as ApiUser & { detail?: unknown };
    if (!response.ok) {
      return { ok: false, error: apiErrorMessage(data, "Couldn't update your profile photo.") };
    }
    const avatarUrl = data.avatar_url ?? undefined;
    setSession(platform, {
      email: data.email,
      name: data.name,
      company: data.company ?? undefined,
      avatarUrl,
      clientId: data.client_id ?? session.clientId,
    });
    syncAvatarAcrossPlatforms(platform, data.email, avatarUrl);
    return { ok: true };
  } catch {
    return { ok: false, error: "Couldn't update your profile photo. Please try again." };
  }
}

export async function removeAvatar(platform: AuthPlatform): Promise<AuthResult> {
  const session = getSession(platform);
  if (!session) return { ok: false, error: "You must be signed in" };

  try {
    const response = await fetch(`${API_BASE}/auth/avatar`, {
      method: "DELETE",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ platform, email: session.email }),
    });
    const data = (await response.json().catch(() => ({}))) as ApiUser & { detail?: unknown };
    if (!response.ok) {
      return { ok: false, error: apiErrorMessage(data, "Couldn't remove your profile photo.") };
    }
    setSession(platform, {
      email: data.email,
      name: data.name,
      company: data.company ?? undefined,
      avatarUrl: null,
      clientId: data.client_id ?? session.clientId,
    });
    syncAvatarAcrossPlatforms(platform, data.email, null);
    return { ok: true };
  } catch {
    return { ok: false, error: "Couldn't remove your profile photo. Please try again." };
  }
}

export async function changePassword(
  platform: AuthPlatform,
  input: { currentPassword: string; newPassword: string },
): Promise<AuthResult> {
  const session = getSession(platform);
  if (!session) return { ok: false, error: "You must be signed in" };
  if (input.newPassword.length < 8) {
    return { ok: false, error: "New password must be at least 8 characters" };
  }

  try {
    const response = await fetch(`${API_BASE}/auth/change-password`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        platform,
        email: session.email,
        current_password: input.currentPassword,
        new_password: input.newPassword,
      }),
    });
    const data = (await response.json().catch(() => ({}))) as { detail?: unknown };
    if (!response.ok) {
      return { ok: false, error: apiErrorMessage(data, "Could not change password") };
    }
    return { ok: true };
  } catch {
    return { ok: false, error: "Could not reach the server. Make sure the API is running." };
  }
}

export async function requestPasswordOtp(
  platform: AuthPlatform,
  email: string,
): Promise<{ ok: true; demoOtp?: string; emailed: boolean; message: string } | { ok: false; error: string }> {
  const normalized = email.trim().toLowerCase();
  if (!normalized || !normalized.includes("@")) {
    return { ok: false, error: "Please enter a valid email" };
  }

  try {
    const response = await fetch(`${API_BASE}/auth/forgot-password/send-otp`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: normalized, platform }),
    });
    const data = (await response.json().catch(() => ({}))) as {
      detail?: unknown;
      message?: string;
      emailed?: boolean;
      demo_otp?: string | null;
    };
    if (!response.ok) {
      return { ok: false, error: apiErrorMessage(data, "Failed to send OTP") };
    }
    return {
      ok: true,
      emailed: Boolean(data.emailed),
      demoOtp: data.demo_otp ?? undefined,
      message: data.message || "OTP sent to your email",
    };
  } catch {
    return {
      ok: false,
      error: "Could not reach the server to send OTP. Make sure the API is running.",
    };
  }
}

export async function verifyPasswordOtp(
  platform: AuthPlatform,
  email: string,
  otp: string,
): Promise<{ ok: true; resetToken: string } | { ok: false; error: string }> {
  const normalized = email.trim().toLowerCase();
  try {
    const response = await fetch(`${API_BASE}/auth/forgot-password/verify-otp`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ email: normalized, platform, otp: otp.trim() }),
    });
    const data = (await response.json().catch(() => ({}))) as {
      detail?: unknown;
      reset_token?: string;
    };
    if (!response.ok || !data.reset_token) {
      return { ok: false, error: apiErrorMessage(data, "Invalid or expired OTP") };
    }
    return { ok: true, resetToken: data.reset_token };
  } catch {
    return { ok: false, error: "Could not verify OTP. Check that the API is running." };
  }
}

export async function resetPasswordWithOtp(
  platform: AuthPlatform,
  email: string,
  resetToken: string,
  newPassword: string,
): Promise<AuthResult> {
  const normalized = email.trim().toLowerCase();
  if (newPassword.length < 8) {
    return { ok: false, error: "Password must be at least 8 characters" };
  }

  try {
    const response = await fetch(`${API_BASE}/auth/forgot-password/confirm`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        email: normalized,
        platform,
        reset_token: resetToken,
        new_password: newPassword,
      }),
    });
    const data = (await response.json().catch(() => ({}))) as { detail?: unknown };
    if (!response.ok) {
      return { ok: false, error: apiErrorMessage(data, "Reset token invalid or expired") };
    }
    return { ok: true };
  } catch {
    return { ok: false, error: "Could not confirm reset. Check that the API is running." };
  }
}

export function initialsFromName(name: string): string {
  return name
    .split(/\s+/)
    .filter(Boolean)
    .map((p) => p[0])
    .join("")
    .slice(0, 2)
    .toUpperCase();
}

export function validateCredentials(email: string, password: string): boolean {
  return email.trim().toLowerCase() === DEMO_EMAIL && password === DEMO_PASSWORD;
}
