// API client — talks to the Cloudflare Worker

const BASE = import.meta.env.VITE_API_BASE ?? '';

function authHeader(): Record<string, string> {
  const token = sessionStorage.getItem('admin_token');
  return token ? { Authorization: `Bearer ${token}` } : {};
}

async function apiFetch(path: string, init: RequestInit = {}): Promise<Response> {
  return fetch(`${BASE}${path}`, {
    ...init,
    headers: {
      'Content-Type': 'application/json',
      ...authHeader(),
      ...(init.headers as Record<string, string> ?? {}),
    },
  });
}

// ---------------------------------------------------------------------------

export interface GeoRule {
  mode: 'allow' | 'block';
  countries: string[];
}

/** 终端与浏览器：与 Worker 内校验逻辑一致 */
export type ClientDevice = 'mobile' | 'desktop';
export type ClientBrowser = 'edge' | 'chrome' | 'safari' | 'firefox' | 'opera' | 'other';

export interface ClientRule {
  /** null 表示不限制 */
  device: ClientDevice | null;
  /**
   * 非空 = 仅允许名单内浏览器；空数组 = 不限制浏览器
   * 与 null 在存储时统一为「无浏览器限制」
   */
  browsers: ClientBrowser[] | null;
}

/** IP 白/黑名单，与边缘 CF-Connecting-IP 比较 */
export interface IpRule {
  mode: 'allow' | 'block';
  /** 支持 IPv4、IPv4 CIDR(如 10.0.0.0/8)、完整 IPv6 地址；最多约 200 条 */
  ips: string[];
}

export interface LinkItem {
  id: number;
  code: string;
  target_url: string;
  expires_at: number | null;
  max_clicks: number | null;
  clicks: number;
  has_password: number;
  geo_rule: string | null; // JSON string of GeoRule, or null
  client_rule: string | null; // JSON string of ClientRule, or null
  ip_rule: string | null; // JSON string of IpRule, or null
  deleted: number;
  created_at: number;
  updated_at: number;
}

export interface CreatePayload {
  target_url: string;
  /**
   * 仅管理员可传：1–32 位，仅 a-zA-Z0-9_-，且不能为「恰好 4 位纯英数字」以免与系统随机短码空间混淆。
   */
  custom_code?: string | null;
  ttl_seconds?: number | null;
  max_clicks?: number | null;
  password?: string | null;
  geo_rule?: GeoRule | null;
  client_rule?: ClientRule | null;
  ip_rule?: IpRule | null;
}

export interface UpdatePayload {
  target_url?: string;
  expires_at?: number | null;
  max_clicks?: number | null;
  password?: string | null;
  clear_password?: boolean;
  geo_rule?: GeoRule | null;
  client_rule?: ClientRule | null;
  ip_rule?: IpRule | null;
  deleted?: number;
}

export async function verifyAdmin(token: string): Promise<boolean> {
  const res = await fetch(`${BASE}/api/auth`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ token }),
  });
  return res.ok;
}

export async function createLink(payload: CreatePayload): Promise<{ code: string; url: string; target_url: string }> {
  const res = await apiFetch('/api/links', { method: 'POST', body: JSON.stringify(payload) });
  if (!res.ok) {
    const data = await res.json().catch(() => ({})) as { error?: string };
    throw new Error(data.error ?? `HTTP ${res.status}`);
  }
  return res.json();
}

export async function listLinks(page = 1, limit = 20): Promise<{ items: LinkItem[]; total: number; page: number; limit: number }> {
  const res = await apiFetch(`/api/links?page=${page}&limit=${limit}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

function encCode(code: string): string {
  return encodeURIComponent(code);
}

export async function getLink(code: string): Promise<LinkItem> {
  const res = await apiFetch(`/api/links/${encCode(code)}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

export async function updateLink(code: string, payload: UpdatePayload): Promise<void> {
  const res = await apiFetch(`/api/links/${encCode(code)}`, { method: 'PATCH', body: JSON.stringify(payload) });
  if (!res.ok) {
    const data = await res.json().catch(() => ({})) as { error?: string };
    throw new Error(data.error ?? `HTTP ${res.status}`);
  }
}

export async function deleteLink(code: string): Promise<void> {
  const res = await apiFetch(`/api/links/${encCode(code)}`, { method: 'DELETE' });
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
}

export interface SiteStats {
  total_links: number;
  total_clicks: number;
  /** 全站页浏览量（由前端进入站点时 POST /api/pv 累计） */
  page_views: number;
}

export async function getStats(): Promise<SiteStats> {
  const res = await fetch(`${BASE}/api/stats`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

/** 全站「浏览量」+1，建议在应用根组件挂载时调用一次（需配合 useRef 避免 Strict 双次） */
/** @returns 是否请求成功（200），失败可再次尝试上报 */
export async function recordPageView(): Promise<boolean> {
  try {
    const res = await fetch(`${BASE}/api/pv`, { method: 'POST', headers: { 'Content-Type': 'application/json' } });
    return res.ok;
  } catch {
    return false;
  }
}
