import axios from "axios";
import { useAuthStore } from "@/store/authStore";

const BASE_URL = "/api";

const apiClient = axios.create({
  baseURL: BASE_URL,
  headers: { "Content-Type": "application/json" },
});

apiClient.interceptors.request.use((config) => {
  const token = useAuthStore.getState().token;
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

// ─── Auth ─────────────────────────────────────────────────────────────────────

interface LoginResponse {
  access_token: string;
  token_type: string;
}

/**
 * POST /auth/login
 * Returns a Bearer access token on success.
 * Throws AxiosError 401 for invalid credentials, 422 for validation errors.
 */
export async function loginApi(
  email: string,
  password: string
): Promise<{ access_token: string }> {
  const response = await apiClient.post<LoginResponse>("/auth/login", {
    email,
    password,
  });
  return { access_token: response.data.access_token };
}

// ─── Domain types (mirror backend schemas) ────────────────────────────────────

export interface TournamentInfo {
  id: number;
  title: string;
  event_date: string; // ISO-8601
}

export interface SeatInfo {
  id: number;
  sector: string;
  row: number;
  number: number;
  price: number;
  tournament: TournamentInfo;
}

export type TicketStatus = "AVAILABLE" | "LOCKED" | "PAID" | "SCANNED" | "REFUNDED";

export interface TicketResponse {
  id: number;
  status: TicketStatus;
  pdf_url: string | null;
  created_at: string; // ISO-8601
  seat: SeatInfo;
}

// ─── Tickets API ──────────────────────────────────────────────────────────────

/**
 * GET /api/tickets/me
 * Returns all PAID tickets for the authenticated user.
 * Throws AxiosError 401 if the token is missing or expired.
 */
export async function getMyTicketsApi(): Promise<TicketResponse[]> {
  const response = await apiClient.get<TicketResponse[]>("/tickets/me");
  return response.data;
}

// ─── Seat locking ─────────────────────────────────────────────────────────────

interface LockSeatResponse {
  message: string;
  seat_id: number;
  status: string;
  /** Returned by backend when the Ticket row is created. Falls back to seat_id. */
  ticket_id?: number;
}

/**
 * POST /api/seats/{seat_id}/lock?user_id={user_id}
 * Returns the ticketId for the locked seat (falls back to seatId if backend
 * does not yet expose ticket_id in the response body).
 * Throws AxiosError with status 409 if the seat is already locked.
 */
export async function lockSeatApi(
  seatId: number,
  userId: number
): Promise<{ ticketId: number }> {
  const response = await apiClient.post<LockSeatResponse>(
    `/seats/${seatId}/lock`,
    null,
    { params: { user_id: userId } }
  );
  return { ticketId: response.data.ticket_id ?? seatId };
}

// ─── Payment webhook ──────────────────────────────────────────────────────────

/**
 * POST /api/webhooks/payment
 * Simulates a payment gateway callback for the given ticket.
 * Uses a random idempotency key to satisfy the backend's idempotency check.
 */
export async function processPaymentWebhook(ticketId: number): Promise<void> {
  const idempotencyKey = "req-" + Math.random().toString(36).substring(2, 9);
  await apiClient.post("/webhooks/payment", {
    ticket_id: ticketId,
    idempotency_key: idempotencyKey,
    status: "success",
  });
}

// ─── Ticket scanner ───────────────────────────────────────────────────────────

export interface ScanResponse {
  success: boolean;
  message: string;
  ticket_id?: number;
}

/**
 * POST /api/tickets/scan
 * Validates a ticket token and marks it as SCANNED.
 * Always resolves (never throws) — 400/404 error bodies are returned as ScanResponse.
 */
export async function scanTicketApi(token: string): Promise<ScanResponse> {
  try {
    const response = await apiClient.post<ScanResponse>("/tickets/scan", { token });
    return response.data;
  } catch (err) {
    const axiosErr = err as import("axios").AxiosError<{ detail: ScanResponse }>;
    // Backend encodes ScanResponse inside HTTPException.detail
    const detail = axiosErr.response?.data?.detail;
    if (detail && typeof detail === "object" && "success" in detail) {
      return detail as ScanResponse;
    }
    return { success: false, message: "Ошибка соединения с сервером" };
  }
}

// ─── Tournament public seats ──────────────────────────────────────────────────

/**
 * Mirrors backend `SeatResponse` schema.
 * `is_available` is false when a LOCKED or PAID ticket exists for this seat.
 */
export interface SeatResponse {
  id: number;
  sector: string;
  row: number;
  number: number;
  price: number;
  is_available: boolean;
}

/**
 * GET /api/tournaments/{tournamentId}/seats
 * Public endpoint — no token required.
 */
export async function getTournamentSeatsApi(
  tournamentId: string | number
): Promise<SeatResponse[]> {
  const response = await apiClient.get<SeatResponse[]>(
    `/tournaments/${tournamentId}/seats`
  );
  return response.data;
}

// ─── Admin: Tournaments ───────────────────────────────────────────────────────

export interface TournamentCreate {
  title: string;
  description?: string;
  event_date: string; // ISO-8601
}

export interface TournamentAdminResponse {
  id: number;
  title: string;
  description: string | null;
  event_date: string;
}

export interface SectorConfigInput {
  sector_name: string;
  rows: number;
  seats_per_row: number;
  price: number;
}

/**
 * POST /api/tournaments
 * Creates a new tournament. Requires a superuser token (403 otherwise).
 */
export async function createTournamentApi(
  data: TournamentCreate
): Promise<TournamentAdminResponse> {
  const response = await apiClient.post<TournamentAdminResponse>("/tournaments", data);
  return response.data;
}

/**
 * POST /api/tournaments/{tournament_id}/generate-seats
 * Bulk-generates seats for a tournament. Requires a superuser token.
 */
export async function generateSeatsApi(
  tournamentId: number,
  sectors: SectorConfigInput[]
): Promise<{ message: string }> {
  const response = await apiClient.post<{ message: string }>(
    `/tournaments/${tournamentId}/generate-seats`,
    { sectors }
  );
  return response.data;
}

export default apiClient;
