import type {
  Campaign,
  Character,
  Gear,
  Talent,
  GameItem,
  GameTalent,
  RollResult,
  Spell,
  CharacterSpell,
  SpellCastResult,
} from "./types";

const BASE = "/api";

async function request<T>(path: string, options?: RequestInit): Promise<T> {
  const res = await fetch(`${BASE}${path}`, {
    headers: { "Content-Type": "application/json" },
    credentials: "include",
    ...options,
  });
  if (!res.ok) {
    const err = await res.json().catch(() => ({ error: res.statusText }));
    throw new Error(err.error || res.statusText);
  }
  if (res.status === 204) return undefined as T;
  return res.json();
}

// Auth
export interface AuthUser {
  userId: number;
  email: string;
  username: string;
}

export const getMe = () => request<AuthUser>("/auth/me");
export const login = (email: string, password: string) =>
  request<AuthUser>("/auth/login", {
    method: "POST",
    body: JSON.stringify({ email, password }),
  });
export const register = (email: string, username: string, password: string) =>
  request<AuthUser>("/auth/register", {
    method: "POST",
    body: JSON.stringify({ email, username, password }),
  });
export const logout = () =>
  request<{ ok: boolean }>("/auth/logout", { method: "POST" });

// Campaigns
export const getCampaigns = () => request<Campaign[]>("/campaigns");
export const createCampaign = (name: string) =>
  request<Campaign>("/campaigns", {
    method: "POST",
    body: JSON.stringify({ name }),
  });
export const deleteCampaign = (id: number) =>
  request<void>(`/campaigns/${id}`, { method: "DELETE" });
export const getMyCampaignRole = (campaignId: number) =>
  request<{ role: "dm" | "player" }>(`/campaigns/${campaignId}/my-role`);
export const generateInvite = (campaignId: number) =>
  request<{ url: string }>(`/campaigns/${campaignId}/invite`, { method: "POST" });
export const joinCampaign = (token: string) =>
  request<{ campaignId: number; role: string }>(`/campaigns/join/${token}`, {
    method: "POST",
  });

// Characters
export const getCharacters = (campaignId: number) =>
  request<Character[]>(`/campaigns/${campaignId}/characters`);
export interface CreateCharacterData {
  name: string;
  class?: string;
  ancestry?: string;
  alignment?: string;
  background?: string;
  deity?: string;
  title?: string;
  hp_max?: number;
  gp?: number;
  stats?: Record<string, number>;
}

export const createCharacter = (campaignId: number, data: CreateCharacterData) =>
  request<Character>(`/campaigns/${campaignId}/characters`, {
    method: "POST",
    body: JSON.stringify(data),
  });
export const updateCharacter = (id: number, data: Partial<Character>) =>
  request<Character>(`/characters/${id}`, {
    method: "PATCH",
    body: JSON.stringify(data),
  });
export const deleteCharacter = (id: number) =>
  request<void>(`/characters/${id}`, { method: "DELETE" });

// Stats
export const updateStat = (characterId: number, statName: string, value: number) =>
  request<{ characterId: number; statName: string; value: number }>(
    `/characters/${characterId}/stats/${statName}`,
    { method: "PATCH", body: JSON.stringify({ value }) },
  );

// Gear
export const addGear = (
  characterId: number,
  data: {
    name: string;
    type?: string;
    slot_count?: number;
    properties?: Record<string, unknown>;
    effects?: Record<string, unknown>;
    game_item_id?: number | null;
  },
) =>
  request<Gear>(`/characters/${characterId}/gear`, {
    method: "POST",
    body: JSON.stringify(data),
  });
export const removeGear = (characterId: number, gearId: number) =>
  request<void>(`/characters/${characterId}/gear/${gearId}`, { method: "DELETE" });

// Talents
export const addTalent = (
  characterId: number,
  data: {
    name: string;
    description?: string;
    effect?: Record<string, unknown>;
    game_talent_id?: number | null;
  },
) =>
  request<Talent>(`/characters/${characterId}/talents`, {
    method: "POST",
    body: JSON.stringify(data),
  });
export const removeTalent = (characterId: number, talentId: number) =>
  request<void>(`/characters/${characterId}/talents/${talentId}`, { method: "DELETE" });

// Game Items
export const getGameItems = () => request<GameItem[]>("/game-items");

// Game Talents
export const getGameTalents = () => request<GameTalent[]>("/game-talents");

// Rolls
export const getRolls = (campaignId: number) =>
  request<RollResult[]>(`/campaigns/${campaignId}/rolls`);

// Spells
export async function getSpells(spellClass?: string): Promise<Spell[]> {
  const qs = spellClass ? `?class=${spellClass}` : "";
  return request<Spell[]>(`/spells${qs}`);
}

export async function getCharacterSpells(characterId: number): Promise<CharacterSpell[]> {
  return request<CharacterSpell[]>(`/characters/${characterId}/spells`);
}

export async function addCharacterSpell(characterId: number, spellId: number): Promise<CharacterSpell> {
  return request<CharacterSpell>(`/characters/${characterId}/spells`, {
    method: "POST",
    body: JSON.stringify({ spell_id: spellId }),
  });
}

export async function removeCharacterSpell(characterId: number, spellId: number): Promise<void> {
  return request<void>(`/characters/${characterId}/spells/${spellId}`, { method: "DELETE" });
}

export async function castSpell(characterId: number, spellId: number): Promise<SpellCastResult> {
  return request<SpellCastResult>(`/characters/${characterId}/spells/${spellId}/cast`, { method: "POST" });
}

export async function restCharacter(characterId: number): Promise<void> {
  return request<void>(`/characters/${characterId}/rest`, { method: "POST" });
}

export async function undoRoll(campaignId: number, rollId: number): Promise<void> {
  return request<void>(`/campaigns/${campaignId}/rolls/${rollId}/undo`, { method: "POST" });
}
