import type {
  AdminDashboardResponse,
  AdminSeasonDetailResponse,
  AdminSeasonListItem,
  AuthSession,
  CreateNominationPayload,
  CreateVotePayload,
  LoginPayload,
  OverviewResponse,
  SeasonCategoriesResponse,
  UpdateSeasonPayload,
  ApproveNominationPayload,
  UpsertCandidatePayload,
  UpsertCategoryPayload,
  WinnerArchiveResponse,
} from '../types/awards'

const API_URL = import.meta.env.VITE_API_URL ?? 'http://127.0.0.1:5084'
const AUTH_TOKEN_KEY = 'vtsa-session-token'

function getAuthToken() {
  if (typeof window === 'undefined') return null
  return window.localStorage.getItem(AUTH_TOKEN_KEY)
}

async function getJson<T>(path: string): Promise<T> {
  const token = getAuthToken()
  const response = await fetch(`${API_URL}${path}`, {
    headers: token
      ? {
          Authorization: `Bearer ${token}`,
        }
      : undefined,
  }).catch(() => {
    throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`)
  })
  if (!response.ok) {
    throw new Error(`API request failed for ${path}`)
  }
  return response.json() as Promise<T>
}

async function sendJson<TResponse>(path: string, method: 'POST' | 'PUT', body: unknown): Promise<TResponse> {
  const token = getAuthToken()
  const response = await fetch(`${API_URL}${path}`, {
    method,
    headers: {
      'Content-Type': 'application/json',
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
    },
    body: JSON.stringify(body),
  }).catch(() => {
    throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`)
  })

  if (!response.ok) {
    const error = await response.text()
    throw new Error(error || `API request failed for ${path}`)
  }

  return response.json() as Promise<TResponse>
}

export const api = {
  getOverview: () => getJson<OverviewResponse>('/api/public/overview'),
  getSeasonCategories: (year: number) =>
    getJson<SeasonCategoriesResponse>(`/api/public/seasons/${year}/categories`),
  getWinnerArchive: (year: number) =>
    getJson<WinnerArchiveResponse>(`/api/public/seasons/${year}/winners`),
  getAdminDashboard: () => getJson<AdminDashboardResponse>('/api/admin/dashboard'),
  getAdminSeasons: () => getJson<AdminSeasonListItem[]>('/api/admin/seasons'),
  getAdminSeasonDetail: (seasonId: number) =>
    getJson<AdminSeasonDetailResponse>(`/api/admin/seasons/${seasonId}`),
  getSession: () => getJson<AuthSession>('/api/auth/session'),
  login: (payload: LoginPayload) => sendJson<AuthSession>('/api/auth/dev-login', 'POST', payload),
  logout: () => sendJson<{ loggedOut: boolean }>('/api/auth/logout', 'POST', {}),
  submitNomination: (payload: CreateNominationPayload) =>
    sendJson<{ saved: number; category: string }>('/api/public/nominations', 'POST', payload),
  submitVote: (payload: CreateVotePayload) =>
    sendJson<{ ballotId: number; entries: number }>('/api/public/votes', 'POST', payload),
  updateAdminSeason: (seasonId: number, payload: UpdateSeasonPayload) =>
    sendJson<{ saved: boolean; seasonId: number }>(`/api/admin/seasons/${seasonId}`, 'PUT', payload),
  createAdminCategory: (seasonId: number, payload: UpsertCategoryPayload) =>
    sendJson<{ saved: boolean; categoryId: number }>(`/api/admin/seasons/${seasonId}/categories`, 'POST', payload),
  updateAdminCategory: (categoryId: number, payload: UpsertCategoryPayload) =>
    sendJson<{ saved: boolean; categoryId: number }>(`/api/admin/categories/${categoryId}`, 'PUT', payload),
  createAdminCandidate: (seasonId: number, payload: UpsertCandidatePayload) =>
    sendJson<{ saved: boolean; candidateId: number }>(`/api/admin/seasons/${seasonId}/candidates`, 'POST', payload),
  updateAdminCandidate: (candidateId: number, payload: UpsertCandidatePayload) =>
    sendJson<{ saved: boolean; candidateId: number }>(`/api/admin/candidates/${candidateId}`, 'PUT', payload),
  approveAdminNomination: (nominationId: number, payload: ApproveNominationPayload) =>
    sendJson<{ saved: boolean; nominationId: number; candidateId: number; created: boolean }>(
      `/api/admin/nominations/${nominationId}/approve`,
      'POST',
      payload,
    ),
  rejectAdminNomination: (nominationId: number) =>
    sendJson<{ saved: boolean; nominationId: number; rejected: boolean }>(
      `/api/admin/nominations/${nominationId}/reject`,
      'POST',
      {},
    ),
  resolveRiskFlag: (riskFlagId: number, status = 'resolved') =>
    sendJson<{ saved: boolean; riskFlagId: number; status: string }>(
      `/api/admin/risk-flags/${riskFlagId}/resolve`,
      'POST',
      { status },
    ),
}

export { AUTH_TOKEN_KEY }
