/**
 * AI 创作 API 层
 *
 * 所有请求经由后端代理 /leai-proxy/* 转发到乐读派
 * 前端不持有 phone/orgId/appSecret，仅通过 JWT 认证调后端代理
 * 后端自动注入 orgId + phone 并使用 HMAC 签名
 */
import OSS from "ali-oss";
import publicApi from "@/api/public";
import type { StsTokenData, CreateStoryParams } from "./types";

// ═══════════════════════════════════════════════════════════
// API 函数（全部走后端代理）
// ═══════════════════════════════════════════════════════════

/** 图片上传 */
export function uploadImage(file: File) {
  const form = new FormData();
  form.append("file", file);
  return publicApi.post("/leai-proxy/upload", form, {
    headers: { "Content-Type": "multipart/form-data" },
    timeout: 30000,
  });
}

/** 角色提取 */
export function extractCharacters(
  imageUrl: string,
  opts: { saveOriginal?: boolean; title?: string } = {},
) {
  const body: Record<string, any> = { imageUrl };
  if (opts.saveOriginal) body.saveOriginal = true;
  if (opts.title) body.title = opts.title;
  return publicApi.post("/leai-proxy/extract", body, { timeout: 120000 });
}

/** 图片故事创作 */
export function createStory(params: CreateStoryParams) {
  const body: Record<string, any> = {
    imageUrl: params.imageUrl,
    storyHint: params.storyHint,
    style: params.style,
    heroName: params.heroName,
    refAdaptMode: params.refAdaptMode || "enhanced",
    enableVoice: false,
  };
  if (params.title) body.title = params.title;
  if (params.author) body.author = params.author;
  if (params.heroCharId) body.heroCharId = params.heroCharId;
  if (params.extractId) body.extractId = params.extractId;
  return publicApi.post("/leai-proxy/create-story", body);
}

/**
 * 乐读派 B2 作品详情：响应体常为 { code, data: Work }，经 public 拦截器可能已剥一层，
 * 仍可能出现嵌套 data，统一解包为 Work 对象（与 CreatingView 原 detail.data 语义一致）。
 */
export function unwrapLeaiWorkDetail(raw: unknown): any {
  let cur: any = raw;
  for (let i = 0; i < 5; i++) {
    if (!cur || typeof cur !== "object") return cur;
    if (cur.workId != null || Array.isArray(cur.pageList)) return cur;
    if (cur.data != null && typeof cur.data === "object") {
      cur = cur.data;
      continue;
    }
    break;
  }
  return cur;
}

/** 查询作品详情 */
export function getWorkDetail(workId: string) {
  return publicApi.get(`/leai-proxy/work/${workId}`).then(unwrapLeaiWorkDetail);
}

/** 额度校验 */
export function checkQuota() {
  return publicApi.post("/leai-proxy/validate", { apiType: "A3" });
}

/** 编辑绘本信息 */
export function updateWork(workId: string, data: Record<string, any>) {
  return publicApi.put(`/leai-proxy/work/${workId}`, data);
}

/** 批量更新配音 URL */
export function batchUpdateAudio(workId: string, pages: any[]) {
  return publicApi.post("/leai-proxy/batch-audio", { workId, pages });
}

/** 完成配音 */
export function finishDubbing(workId: string) {
  return batchUpdateAudio(workId, []);
}

/** AI 配音 */
export function voicePage(data: Record<string, any>) {
  return publicApi.post("/leai-proxy/voice", data, { timeout: 120000 });
}

/** STS 临时凭证（经后端代理获取） */
export function getStsToken() {
  return publicApi.post("/leai-proxy/sts-token");
}

// ─── OSS 直传 ──
let _ossClient: OSS | null = null;
let _stsData: StsTokenData | null = null;

async function getOssClient() {
  if (_ossClient && _stsData) {
    const expireTime = new Date(_stsData.expiration).getTime();
    if (Date.now() < expireTime - 5 * 60 * 1000) {
      return { client: _ossClient, prefix: _stsData.uploadPrefix };
    }
  }
  const res = await getStsToken();
  _stsData = res as StsTokenData;
  _ossClient = new OSS({
    region: _stsData.region,
    accessKeyId: _stsData.accessKeyId,
    accessKeySecret: _stsData.accessKeySecret,
    stsToken: _stsData.securityToken,
    bucket: _stsData.bucket,
    endpoint: _stsData.endpoint,
    refreshSTSToken: async () => {
      const r = await getStsToken();
      _stsData = r as StsTokenData;
      return {
        accessKeyId: _stsData.accessKeyId,
        accessKeySecret: _stsData.accessKeySecret,
        stsToken: _stsData.securityToken,
      };
    },
    refreshSTSTokenInterval: 300000,
  });
  return { client: _ossClient, prefix: _stsData.uploadPrefix };
}

/**
 * STS 直传文件到 OSS
 * @param file 要上传的文件
 * @param opts 选项
 * @returns 文件的完整 OSS URL
 */
export async function ossUpload(
  file: File | Blob,
  opts: {
    type?: string;
    onProgress?: (pct: number) => void;
    ext?: string;
  } = {},
): Promise<string> {
  const { type = "img", onProgress, ext: forceExt } = opts;
  const { client, prefix } = await getOssClient();
  const ext =
    forceExt ||
    ((file as File).name
      ? (file as File).name.split(".").pop()
      : "bin"
    ).toLowerCase();
  const date = new Date().toISOString().slice(0, 10);
  const rand = Math.random().toString(36).slice(2, 10);
  const key = `${prefix}${date}/${type}_${Date.now()}_${rand}.${ext}`;
  await (client as OSS).put(key, file, {
    headers: { "x-oss-object-acl": "public-read" },
    progress: (p: number) => {
      if (onProgress) onProgress(Math.round(p * 100));
    },
  });
  if (_stsData!.cdnDomain) {
    return `${_stsData!.cdnDomain}/${key}`;
  }
  return `https://${_stsData!.bucket}.${_stsData!.endpoint.replace("https://", "")}/${key}`;
}

/** STS 列举用户目录下的文件 */
export async function ossListFiles() {
  const { client, prefix } = await getOssClient();
  const result = await (client as OSS).list({ prefix, "max-keys": 100 });
  return (result.objects || []).map((obj: any) => ({
    name: obj.name.replace(prefix, ""),
    size: obj.size,
    lastModified: obj.lastModified,
    url: obj.url,
  }));
}
