import type {
  AITask,
  Asset,
  AuthPayload,
  BillingSummary,
  Ledger,
  ModelConfig,
  Notification,
  NotificationList,
  Paginated,
  Product,
  Project,
  RechargeResult,
  ScriptVersion,
  Team,
  TeamMember,
  User
} from "./types";

const API_BASE = import.meta.env.VITE_API_BASE_URL || "";
const TOKEN_KEY = "airshelf_token";

export class ApiError extends Error {
  status: number;

  constructor(status: number, message: string) {
    super(message);
    this.name = "ApiError";
    this.status = status;
  }
}

export function getToken() {
  return localStorage.getItem(TOKEN_KEY);
}

export function setToken(token: string | null) {
  if (token) localStorage.setItem(TOKEN_KEY, token);
  else localStorage.removeItem(TOKEN_KEY);
}

async function request<T>(path: string, options: RequestInit = {}): Promise<T> {
  const token = getToken();
  const headers = new Headers(options.headers);
  if (!(options.body instanceof FormData)) {
    headers.set("Content-Type", "application/json");
  }
  if (token) headers.set("Authorization", `Token ${token}`);

  const response = await fetch(`${API_BASE}${path}`, { ...options, headers });
  if (!response.ok) {
    const text = await response.text();
    throw new ApiError(response.status, text || `${response.status} ${response.statusText}`);
  }
  if (response.status === 204) return undefined as T;
  return response.json() as Promise<T>;
}

export const api = {
  register(payload: { username: string; password: string; email?: string; team_name?: string }) {
    return request<AuthPayload>("/api/auth/register/", { method: "POST", body: JSON.stringify(payload) });
  },
  login(payload: { username: string; password: string }) {
    return request<AuthPayload>("/api/auth/login/", { method: "POST", body: JSON.stringify(payload) });
  },
  me() {
    return request<{ user: User; team: Team }>("/api/auth/me/");
  },
  updateProfile(payload: { name?: string; phone?: string; email?: string }) {
    return request<{ user: User; team: Team }>("/api/auth/me/", { method: "PATCH", body: JSON.stringify(payload) });
  },
  changePassword(payload: { old_password: string; new_password: string }) {
    return request<{ token: string }>("/api/auth/me/password/", { method: "POST", body: JSON.stringify(payload) });
  },
  uploadAvatar(formData: FormData) {
    return request<User>("/api/auth/me/avatar/", { method: "POST", body: formData });
  },
  logout() {
    return request<void>("/api/auth/logout/", { method: "POST" });
  },
  teamMembers() {
    return request<TeamMember[]>("/api/auth/team/members/");
  },
  createTeamMember(payload: {
    username: string;
    password: string;
    name?: string;
    email?: string;
    role?: string;
    monthly_credit_limit?: number | string;
  }) {
    return request<TeamMember>("/api/auth/team/members/", { method: "POST", body: JSON.stringify(payload) });
  },
  updateTeamMember(id: string, payload: { role?: string; monthly_credit_limit?: number | string; name?: string }) {
    return request<TeamMember>(`/api/auth/team/members/${id}/`, { method: "PATCH", body: JSON.stringify(payload) });
  },
  removeTeamMember(id: string) {
    return request<void>(`/api/auth/team/members/${id}/`, { method: "DELETE" });
  },
  resetMemberPassword(id: string, password: string) {
    return request<void>(`/api/auth/team/members/${id}/password/`, {
      method: "POST",
      body: JSON.stringify({ password })
    });
  },
  products() {
    return request<Paginated<Product>>("/api/products/");
  },
  product(id: string) {
    return request<Product>(`/api/products/${id}/`);
  },
  createProduct(payload: {
    title?: string;
    brand?: string;
    category?: string;
    target_audience?: string;
    description?: string;
    specs?: Record<string, unknown>;
    selling_points?: Array<{ title: string; detail: string; sort_order: number }>;
  }) {
    return request<Product>("/api/products/", { method: "POST", body: JSON.stringify(payload) });
  },
  updateProduct(id: string, payload: Partial<Product>) {
    return request<Product>(`/api/products/${id}/`, { method: "PATCH", body: JSON.stringify(payload) });
  },
  deleteProduct(id: string) {
    return request<void>(`/api/products/${id}/`, { method: "DELETE" });
  },
  projects() {
    return request<Paginated<Project>>("/api/projects/");
  },
  project(id: string) {
    return request<Project>(`/api/projects/${id}/`);
  },
  createProject(payload: { name: string; product: string }) {
    return request<Project>("/api/projects/", { method: "POST", body: JSON.stringify(payload) });
  },
  deleteProject(id: string) {
    return request<void>(`/api/projects/${id}/`, { method: "DELETE" });
  },
  generateScript(projectId: string, payload: { prompt: string; selling_point_ids?: string[] }) {
    return request<ScriptVersion>(`/api/projects/${projectId}/generate-script/`, {
      method: "POST",
      body: JSON.stringify(payload)
    });
  },
  adoptScript(projectId: string, script_version_id: string) {
    return request<ScriptVersion>(`/api/projects/${projectId}/adopt-script/`, {
      method: "POST",
      body: JSON.stringify({ script_version_id })
    });
  },
  generateBaseAsset(projectId: string, payload: { kind: "product" | "person" | "scene"; prompt: string }) {
    return request(`/api/projects/${projectId}/generate-base-asset/`, { method: "POST", body: JSON.stringify(payload) });
  },
  adoptBaseAsset(projectId: string, payload: { group_id: string; asset_id: string }) {
    return request(`/api/projects/${projectId}/adopt-base-asset/`, { method: "POST", body: JSON.stringify(payload) });
  },
  generateStoryboard(projectId: string, payload: { prompt: string }) {
    return request(`/api/projects/${projectId}/generate-storyboard/`, { method: "POST", body: JSON.stringify(payload) });
  },
  skipStoryboard(projectId: string) {
    return request<Project>(`/api/projects/${projectId}/skip-storyboard/`, { method: "POST" });
  },
  submitVideo(projectId: string, payload: { video_segment_id: string; prompt: string }) {
    return request<Project>(`/api/projects/${projectId}/submit-video-segment/`, { method: "POST", body: JSON.stringify(payload) });
  },
  pollVideo(projectId: string, video_segment_id: string) {
    return request(`/api/projects/${projectId}/poll-video-segment/`, {
      method: "POST",
      body: JSON.stringify({ video_segment_id })
    });
  },
  submitExport(projectId: string) {
    return request(`/api/projects/${projectId}/submit-export/`, { method: "POST" });
  },
  assets() {
    return request<Paginated<Asset>>("/api/assets/");
  },
  uploadAsset(formData: FormData) {
    return request<Asset>("/api/assets/upload/", { method: "POST", body: formData });
  },
  billingSummary() {
    return request<BillingSummary>("/api/billing/summary/");
  },
  ledgers() {
    return request<Ledger[]>("/api/billing/ledgers/");
  },
  modelConfigs() {
    return request<Paginated<ModelConfig>>("/api/ai/models/");
  },
  aiTasks() {
    return request<Paginated<AITask>>("/api/ai/tasks/");
  },
  generateImage(payload: { prompt: string; mode?: "image" | "model" | "cover"; count?: number }) {
    return request<{ assets: Asset[] }>("/api/ai/generate-image/", { method: "POST", body: JSON.stringify(payload) });
  },
  recharge(payload: { amount: number | string; bonus?: number | string; channel?: string }) {
    return request<RechargeResult>("/api/billing/recharge/", { method: "POST", body: JSON.stringify(payload) });
  },
  listNotifications(params?: { type?: string; unread?: boolean }) {
    const query = new URLSearchParams();
    if (params?.type && params.type !== "all") query.set("type", params.type);
    if (params?.unread) query.set("unread", "1");
    const qs = query.toString();
    return request<NotificationList>(`/api/ops/notifications/${qs ? `?${qs}` : ""}`);
  },
  markAllNotificationsRead() {
    return request<{ updated: number; unread_count: number }>("/api/ops/notifications/mark-all-read/", {
      method: "POST"
    });
  },
  markNotificationRead(id: string) {
    return request<Notification>(`/api/ops/notifications/${id}/mark-read/`, { method: "POST" });
  }
};
