export type TraitScores = {
  aggression: number;
  stability: number;
  roaming: number;
  vision: number;
  objective: number;
  growth: number;
  fightJoin: number;
};

export type RankedQueueSummary = {
  tier: string;
  rank: string;
  leaguePoints: number;
  wins: number;
  losses: number;
};

export type MatchQueueFilter = 'ALL' | 'RANKED_SOLO' | 'RANKED_FLEX' | 'ARAM' | 'GAME_TYPES';

export type AnalysisSnapshot = {
  snapshotId: string;
  gameName?: string;
  tagLine?: string;
  profileIconId?: number | null;
  summonerLevel?: number | null;
  analyzedAt?: string | null;
  currentRanks?: {
    solo: RankedQueueSummary | null;
    flex: RankedQueueSummary | null;
  };
  ggtiType: string;
  sampleMatchCount: number;
  primaryChampionName: string | null;
  traitScores: TraitScores;
  featureSummary: Record<string, unknown>;
  aiSummary: string | null;
  aiDetail: string | null;
  shareKey: string | null;
  totalMatchCount?: number;
  recentMatches?: Array<{
    participantMatchId: string;
    matchId: string;
    queueId: number;
    gameStartAt: string;
    gameDurationSec: number;
    championName: string;
    lane: string | null;
    role: string | null;
    win: boolean;
    kills: number;
    deaths: number;
    assists: number;
    killParticipation: number | null;
    visionScore: number;
    totalMinionsKilled: number;
    goldEarned: number;
    totalDamageToChampions: number;
    items: number[];
    summonerSpellIds: number[];
    kdaRatio: number;
    featureScores: TraitScores | null;
    aiSummary: string;
    aiDetail: string;
    tags: string[];
  }>;
};

export type RecentMatchSummary = NonNullable<AnalysisSnapshot['recentMatches']>[number];

export type RiotAccountSuggestion = {
  puuid: string;
  gameName: string;
  tagLine: string;
  displayName: string;
  source: 'LOCAL_CACHE';
  lastSyncedAt: string | null;
};

export type MatchDetailParticipant = {
  participantId: number;
  teamId: number;
  championId: number;
  championName: string | null;
  summonerName: string;
  tagLine: string | null;
  puuid: string | null;
  level: number;
  win: boolean;
  kills: number;
  deaths: number;
  assists: number;
  kdaRatio: number;
  killParticipation: number | null;
  visionScore: number;
  wardsPlaced: number;
  wardsKilled: number;
  controlWardsBought: number;
  totalDamageToChampions: number;
  totalDamageTaken: number;
  cs: number;
  csPerMinute: number;
  spells: number[];
  items: number[];
  perks: number[];
  isPlayer: boolean;
  goldEarned: number;
};

export type MatchDetail = {
  participantMatchId: string;
  matchId: string;
  queueId: number;
  gameStartAt: string;
  gameDurationSec: number;
  teamId: number;
  win: boolean;
  aiSummary: string;
  aiDetail: string;
  tags: string[];
  player: {
    participantId: number;
    teamId: number;
    gameName: string;
    tagLine: string | null;
  };
  teams: Array<{
    teamId: number;
    side: 'BLUE' | 'RED';
    result: 'Victory' | 'Defeat';
    totalKills: number;
    totalGold: number;
    objectives: {
      baron: number;
      dragon: number;
      riftHerald: number;
      horde: number;
      tower: number;
      inhibitor: number;
    };
    participants: MatchDetailParticipant[];
  }>;
  playerTeamSide: 'BLUE' | 'RED';
};

export type ChampionSuggestion = {
  key: string;
  name: string;
  title: string;
  imageUrl: string | null;
};

type ApiResponse<T> = {
  success: boolean;
  data: T | null;
  error: { code: string; message: string } | null;
};

const DEFAULT_SERVER_API_BASE_URL = 'http://127.0.0.1:6601/api';
const DEFAULT_BROWSER_API_BASE_URL = '/api';

function getApiBaseUrl() {
  if (typeof window === 'undefined') {
    return process.env.SERVER_API_BASE_URL ?? process.env.NEXT_PUBLIC_API_BASE_URL ?? DEFAULT_SERVER_API_BASE_URL;
  }

  return process.env.NEXT_PUBLIC_API_BASE_URL ?? DEFAULT_BROWSER_API_BASE_URL;
}

export async function createAnalysis(input: {
  snapshotId?: number;
  gameName: string;
  tagLine: string;
  region: string;
  matchCount?: number;
}) {
  return apiPost<{ requestId: string; status: string; latestSnapshotId: string | null }>(
    '/v1/analysis',
    input,
  );
}

export async function lookupAnalysis(input: {
  gameName: string;
  tagLine: string;
  region: string;
  syncIfMissing?: boolean;
}) {
  const params = new URLSearchParams({
    gameName: input.gameName,
    tagLine: input.tagLine,
    region: input.region,
    syncIfMissing: String(input.syncIfMissing ?? true),
  });
  return apiGet<{
    found: boolean;
    latestSnapshotId: string | null;
    snapshot: AnalysisSnapshot | null;
    pendingRequestId: string | null;
    pendingStatus: string | null;
    lastUpdatedAt: string | null;
  }>(`/v1/analysis/lookup?${params.toString()}`);
}

export async function refreshAnalysis(input: {
  snapshotId?: number | string;
  gameName: string;
  tagLine: string;
  region: string;
  matchCount?: number;
}) {
  return apiPost<{ requestId: string; status: string; latestSnapshotId: string | null }>(
    '/v1/analysis/refresh',
    input,
  );
}

export async function getRiotAccountSuggestions(input: { query: string; tagLine?: string | null }) {
  if (input.query.trim().length < 1) return [];
  const params = new URLSearchParams({ query: input.query, limit: '6' });
  if (input.tagLine?.trim()) {
    params.set('tagLine', input.tagLine.trim());
  }
  return apiGet<RiotAccountSuggestion[]>(`/v1/riot/suggestions?${params.toString()}`);
}

export async function getChampionSuggestions(query: string) {
  if (query.trim().length < 1) return [];
  const params = new URLSearchParams({ query, limit: '6' });
  return apiGet<ChampionSuggestion[]>(`/v1/riot/champions?${params.toString()}`);
}

export async function getSnapshot(snapshotId: string) {
  return apiGet<AnalysisSnapshot>(`/v1/analysis/snapshots/${snapshotId}`);
}

export async function getSnapshotMatches(
  snapshotId: string,
  offset = 0,
  limit = 20,
  queueFilter: MatchQueueFilter = 'ALL',
) {
  const params = new URLSearchParams({
    offset: String(offset),
    limit: String(limit),
    queueFilter,
  });
  return apiGet<{
    items: RecentMatchSummary[];
    total: number;
    nextOffset: number;
    hasMore: boolean;
  }>(`/v1/analysis/snapshots/${snapshotId}/matches?${params.toString()}`);
}

export async function getAnalysisRequest(requestId: string) {
  return apiGet<{
    id: string;
    status: string;
    errorMessage?: string | null;
    latestSnapshotId: string | null;
    lastUpdatedAt: string | null;
  }>(`/v1/analysis/requests/${requestId}`);
}

export async function getMatchDetail(participantMatchId: string) {
  return apiGet<MatchDetail>(`/v1/analysis/matches/${participantMatchId}`);
}

export async function getShare(shareKey: string) {
  return apiGet<{
    shareKey: string;
    title: string;
    description: string;
    imageUrl: string | null;
    snapshot: AnalysisSnapshot & { gameName: string; tagLine: string };
  }>(`/v1/share/${shareKey}`);
}

export async function createDuo(input: {
  playerA: { gameName: string; tagLine: string; region: string };
  playerB: { gameName: string; tagLine: string; region: string };
}) {
  return apiPost<{
    compatibilityScore: number;
    relationType: string;
    summary: string;
    traitDiff: Record<string, number>;
  }>('/v1/duo', input);
}

async function apiGet<T>(path: string) {
  const res = await fetch(`${getApiBaseUrl()}${path}`, { cache: 'no-store' });
  return unwrap<T>(await res.json());
}

async function apiPost<T>(path: string, body: unknown) {
  const res = await fetch(`${getApiBaseUrl()}${path}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
    cache: 'no-store',
  });
  return unwrap<T>(await res.json());
}

function unwrap<T>(response: ApiResponse<T>) {
  if (!response.success || !response.data) {
    throw new Error(response.error?.message ?? 'API request failed');
  }
  return response.data;
}
