import { serverApiBase } from "./config";
import type {
  CharacterListResponse,
  DraftView,
  ForeshadowBoardResponse,
  OutlineChapterView,
  OutlineResponse,
  ProjectListResponse,
  ProjectResponse,
  OAuthStatusResponse,
  ProvidersResponse,
  ReviewHistoryResponse,
  RuleListResponse,
  SkillListResponse,
  StyleFingerprintResponse,
  TemplateResponse,
  ToolboxListResponse,
  WorldEntityListResponse,
} from "./types";

// 解析 JSON 响应体并做最小运行时校验：非 null 对象/数组才放行，
// 否则抛结构化错误（后端契约保证为 JSON 对象；防御被代理/网关污染的非 JSON 响应）。
// 校验通过后 narrow 到 T（OpenAPI 生成类型为权威形状，此处仅守边界非 null）。
async function parseJsonBody<T>(res: Response, path: string): Promise<T> {
  let body: unknown;
  try {
    body = await res.json();
  } catch {
    throw new Error(`响应非 JSON：${path}`);
  }
  if (typeof body !== "object" || body === null) {
    throw new Error(`响应体形状异常（期望对象）：${path}`);
  }
  return body as T;
}

// 服务端只读取数据（Server Components）。失败时抛出，由页面边界处理。
async function getJson<T>(path: string): Promise<T> {
  const res = await fetch(`${serverApiBase()}${path}`, { cache: "no-store" });
  if (!res.ok) {
    throw new Error(`请求失败 ${res.status}: ${path}`);
  }
  return parseJsonBody<T>(res, path);
}

// 像上面一样读取，但 404（无指纹）返回 null 而非抛出（首学前页面照常渲染）。
async function getJsonOrNull<T>(path: string): Promise<T | null> {
  const res = await fetch(`${serverApiBase()}${path}`, { cache: "no-store" });
  if (res.status === 404) return null;
  if (!res.ok) {
    throw new Error(`请求失败 ${res.status}: ${path}`);
  }
  return parseJsonBody<T>(res, path);
}

export async function fetchProjects(): Promise<ProjectListResponse> {
  return getJson<ProjectListResponse>("/projects");
}

export async function fetchProject(projectId: string): Promise<ProjectResponse> {
  return getJson<ProjectResponse>(`/projects/${projectId}`);
}

export async function fetchProviders(): Promise<ProvidersResponse> {
  return getJson<ProvidersResponse>("/settings/providers");
}

// Kimi Code OAuth 连接态（GET .../oauth/status；无 token 本体）。
export async function fetchKimiOauthStatus(): Promise<OAuthStatusResponse> {
  return getJson<OAuthStatusResponse>(
    "/settings/providers/kimi-code/oauth/status",
  );
}

export async function fetchReviews(
  projectId: string,
  chapterNo: number,
): Promise<ReviewHistoryResponse> {
  return getJson<ReviewHistoryResponse>(
    `/projects/${projectId}/chapters/${chapterNo}/reviews`,
  );
}

// 伏笔看板（全量，前端按 status 分四泳道）。
export async function fetchForeshadow(
  projectId: string,
): Promise<ForeshadowBoardResponse> {
  return getJson<ForeshadowBoardResponse>(`/projects/${projectId}/foreshadow`);
}

// 最新文风指纹（GET /style）；无指纹（404）→ null（首学前页面照常渲染）。
export async function fetchStyleFingerprint(
  projectId: string,
): Promise<StyleFingerprintResponse | null> {
  return getJsonOrNull<StyleFingerprintResponse>(
    `/projects/${projectId}/style`,
  );
}

// 规则列表（GET .../rules，规则页）。
export async function fetchRules(
  projectId: string,
): Promise<RuleListResponse> {
  return getJson<RuleListResponse>(`/projects/${projectId}/rules`);
}

// 技能库注册表（GET /skills，全局只读）。
export async function fetchSkills(): Promise<SkillListResponse> {
  return getJson<SkillListResponse>("/skills");
}

// 创作工具箱描述符（GET /skills/toolbox，全局只读）。
// 任何错误（含后端未上线）降级为空列表，工具箱页照常渲染（不阻塞进页）。
export async function fetchToolbox(): Promise<ToolboxListResponse> {
  try {
    return await getJson<ToolboxListResponse>("/skills/toolbox");
  } catch {
    return { tools: [] };
  }
}

// 设定库 Codex：跨会话全量已入库角色（GET .../characters；无行→空列表，非 404）。
export async function fetchCharacters(
  projectId: string,
): Promise<CharacterListResponse> {
  return getJson<CharacterListResponse>(`/projects/${projectId}/characters`);
}

// 设定库 Codex：跨会话全量已入库世界观实体（GET .../world_entities；无行→空列表）。
export async function fetchWorldEntities(
  projectId: string,
): Promise<WorldEntityListResponse> {
  return getJson<WorldEntityListResponse>(
    `/projects/${projectId}/world_entities`,
  );
}

// 已存大纲（GET .../outline，与 POST 同形，按 chapter_no 排序）。
// 无大纲→空列表；任何错误亦降级为空（进页不阻塞，生成流照常工作）。
export async function fetchOutline(
  projectId: string,
): Promise<OutlineChapterView[]> {
  try {
    const res = await getJson<OutlineResponse>(
      `/projects/${projectId}/outline`,
    );
    return res.chapters ?? [];
  } catch {
    return [];
  }
}

// 提示词/模板库列表（GET /templates，全局只读；裸数组）。
// 任何错误（含后端未上线）降级为空列表，模板页照常渲染（进页不阻塞）。
export async function fetchTemplates(): Promise<TemplateResponse[]> {
  try {
    return await getJson<TemplateResponse[]>("/templates");
  } catch {
    return [];
  }
}

// 已存草稿（GET .../draft，含正文，供工作台重访重载编辑器）。
// 404（尚无草稿，新章）→ null，由调用方当空编辑器处理，不抛错。
export async function fetchDraft(
  projectId: string,
  chapterNo: number,
): Promise<DraftView | null> {
  return getJsonOrNull<DraftView>(
    `/projects/${projectId}/chapters/${chapterNo}/draft`,
  );
}
