export type User = {
  id: string;
  email: string;
  first_name: string | null;
  last_name: string | null;
  role: "USER" | "PARTNER" | "ADMIN" | "SUPER_ADMIN";
  status: "ACTIVE" | "SUSPENDED" | "PENDING_VERIFICATION" | "DELETED";
};

export type AuthResponse = {
  accessToken: string;
  user: User;
};

export type LoginInput = {
  email: string;
  password: string;
};

export type SignupInput = LoginInput & {
  firstName?: string;
  lastName?: string;
};

type UserResponse = { user: User };

export class ApiError extends Error {
  constructor(
    message: string,
    public status: number,
  ) {
    super(message);
    this.name = "ApiError";
  }
}

export const API_URL = (process.env.NEXT_PUBLIC_API_URL ?? "http://localhost:8000/api/v1").replace(/\/$/, "");
const TOKEN_KEY = "encostay_access_token";

export const authToken = {
  get: () => (typeof window === "undefined" ? null : localStorage.getItem(TOKEN_KEY)),
  set: (token: string) => {
    if (typeof window !== "undefined") localStorage.setItem(TOKEN_KEY, token);
  },
  clear: () => {
    if (typeof window !== "undefined") localStorage.removeItem(TOKEN_KEY);
  },
};

async function request<T>(path: string, init: RequestInit = {}): Promise<T> {
  const token = authToken.get();
  const headers = new Headers(init.headers);
  headers.set("Accept", "application/json");
  headers.set("Content-Type", "application/json");
  if (token) headers.set("Authorization", `Bearer ${token}`);
  const response = await fetch(`${API_URL}${path}`, {
    ...init,
    headers,
  });

  const body: unknown = await response.json().catch(() => null);
  if (!response.ok) {
    const message =
      typeof body === "object" && body !== null && "message" in body && typeof body.message === "string"
        ? body.message
        : undefined;
    throw new ApiError(message || "Something went wrong. Please try again.", response.status);
  }
  return body as T;
}

export const api = {
  login: (input: LoginInput) =>
    request<AuthResponse>("/auth/login", { method: "POST", body: JSON.stringify(input) }),
  signup: (input: SignupInput) =>
    request<AuthResponse>("/auth/register", { method: "POST", body: JSON.stringify(input) }),
  me: async () => (await request<UserResponse>("/auth/me")).user,
  logout: async () => {
    try {
      await request<{ message: string }>("/auth/logout", { method: "POST" });
    } finally {
      authToken.clear();
    }
  },
};
