/** Cliente HTTP mínimo hacia el backend FastAPI. Maneja el JWT en localStorage. */
import type {
  AuthResponse,
  Country,
  Genre,
  MediaItem,
  Musician,
  ServiceType,
  User,
} from "./types";

/** Datos editables del perfil de músico (espejo de MusicianUpsertIn). */
export interface MusicianInput {
  stage_name: string;
  bio?: string | null;
  show_description?: string | null;
  years_experience?: number | null;
  service_types: string[];
  genres: string[];
  base_price: number;
  currency: string;
  travel_radius_km: number;
  city?: string | null;
  country: string;
}

const API_URL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:8000";
const TOKEN_KEY = "gotagig_token";

export function getToken(): string | null {
  if (typeof window === "undefined") return null;
  return localStorage.getItem(TOKEN_KEY);
}

export function setToken(token: string) {
  localStorage.setItem(TOKEN_KEY, token);
}

export function clearToken() {
  localStorage.removeItem(TOKEN_KEY);
}

async function request<T>(path: string, options: RequestInit = {}): Promise<T> {
  const token = getToken();
  const res = await fetch(`${API_URL}${path}`, {
    ...options,
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(options.headers || {}),
    },
  });

  if (!res.ok) {
    let detail = `Error ${res.status}`;
    try {
      const body = await res.json();
      if (body?.detail) detail = typeof body.detail === "string" ? body.detail : detail;
    } catch {
      /* respuesta sin JSON */
    }
    throw new Error(detail);
  }
  // 204 sin cuerpo
  if (res.status === 204) return undefined as T;
  return res.json() as Promise<T>;
}

// ---- Auth ----
export const api = {
  register: (data: {
    email: string;
    password: string;
    full_name: string;
    phone?: string;
    role?: string;
    country?: string;
  }) => request<AuthResponse>("/auth/register", { method: "POST", body: JSON.stringify(data) }),

  login: (data: { email: string; password: string }) =>
    request<AuthResponse>("/auth/login", { method: "POST", body: JSON.stringify(data) }),

  me: () => request<User>("/auth/me"),

  // ---- Catálogo ----
  serviceTypes: () => request<ServiceType[]>("/service-types"),
  genres: () => request<Genre[]>("/genres"),
  countries: () => request<Country[]>("/countries"),

  // ---- Búsqueda ----
  search: (params: {
    lat: number;
    lng: number;
    radius_km?: number;
    service_type?: string;
    country?: string;
    available_only?: boolean;
  }) => {
    const q = new URLSearchParams();
    q.set("lat", String(params.lat));
    q.set("lng", String(params.lng));
    if (params.radius_km != null) q.set("radius_km", String(params.radius_km));
    if (params.service_type) q.set("service_type", params.service_type);
    if (params.country) q.set("country", params.country);
    if (params.available_only != null) q.set("available_only", String(params.available_only));
    return request<Musician[]>(`/search?${q.toString()}`);
  },

  musician: (id: number) => request<Musician>(`/musicians/${id}`),

  // ---- Mi perfil de músico (autenticado) ----
  myProfile: () => request<Musician | null>("/musicians/me"),

  upsertProfile: (data: MusicianInput) =>
    request<Musician>("/musicians/me", { method: "PUT", body: JSON.stringify(data) }),

  updateLocation: (data: { lat: number; lng: number; is_available?: boolean }) =>
    request<Musician>("/musicians/me/location", { method: "PATCH", body: JSON.stringify(data) }),

  addVideo: (data: { url: string; caption?: string; is_featured?: boolean }) =>
    request<MediaItem>("/musicians/me/media/video", { method: "POST", body: JSON.stringify(data) }),

  deleteMedia: (id: number) =>
    request<void>(`/musicians/me/media/${id}`, { method: "DELETE" }),

  // Upload de foto: multipart, sin el header JSON (el browser pone el boundary).
  uploadPhoto: async (file: File): Promise<MediaItem> => {
    const token = getToken();
    const form = new FormData();
    form.append("file", file);
    const res = await fetch(`${API_URL}/musicians/me/media/photo`, {
      method: "POST",
      headers: token ? { Authorization: `Bearer ${token}` } : {},
      body: form,
    });
    if (!res.ok) {
      let detail = `Error ${res.status}`;
      try {
        const b = await res.json();
        if (typeof b?.detail === "string") detail = b.detail;
      } catch {
        /* sin JSON */
      }
      throw new Error(detail);
    }
    return res.json() as Promise<MediaItem>;
  },

  // ---- Contrataciones ----
  createBooking: (data: {
    musician_id: number;
    service_type: string;
    mode: string;
    scheduled_at?: string;
    lat?: number;
    lng?: number;
    address?: string;
    notes?: string;
  }) => request("/bookings", { method: "POST", body: JSON.stringify(data) }),
};
