/**
 * 云帧API 供应商适配
 * @version 2.0
 */

// ============================================================
// 类型定义
// ============================================================

type VideoMode =
 | "singleImage"
 | "startEndRequired"
 | "endFrameOptional"
 | "startFrameOptional"
 | "text"
 | (`videoReference:${number}` | `imageReference:${number}` | `audioReference:${number}`)[];

interface TextModel {
 name: string;
 modelName: string;
 type: "text";
 think: boolean;
}

interface ImageModel {
 name: string;
 modelName: string;
 type: "image";
 mode: ("text" | "singleImage" | "multiReference")[];
 associationSkills?: string;
}

interface VideoModel {
 name: string;
 modelName: string;
 type: "video";
 mode: VideoMode[];
 associationSkills?: string;
 audio: "optional" | false | true;
 durationResolutionMap: { duration: number[]; resolution: string[] }[];
}

interface TTSModel {
 name: string;
 modelName: string;
 type: "tts";
 voices: { title: string; voice: string }[];
}

interface VendorConfig {
 id: string;
 version: string;
 name: string;
 author: string;
 description?: string;
 icon?: string;
 inputs: { key: string; label: string; type: "text" | "password" | "url"; required: boolean; placeholder?: string }[];
 inputValues: Record<string, string>;
 models: (TextModel | ImageModel | VideoModel | TTSModel)[];
}

type ReferenceList =
 | { type: "image"; sourceType: "base64"; base64: string }
 | { type: "audio"; sourceType: "base64"; base64: string }
 | { type: "video"; sourceType: "base64"; base64: string };

interface ImageConfig {
 prompt: string;
 referenceList?: Extract<ReferenceList, { type: "image" }>[];
 size: "1K" | "2K" | "4K";
 aspectRatio: `${number}:${number}`;
}

interface VideoConfig {
 duration: number;
 resolution: string;
 aspectRatio: "16:9" | "9:16";
 prompt: string;
 referenceList?: ReferenceList[];
 audio?: boolean;
 mode: VideoMode[];
}

interface TTSConfig {
 text: string;
 voice: string;
 speechRate: number;
 pitchRate: number;
 volume: number;
 referenceList?: Extract<ReferenceList, { type: "audio" }>[];
}

interface PollResult {
 completed: boolean;
 data?: string;
 error?: string;
}

// ============================================================
// 全局声明
// ============================================================

declare const axios: any;
declare const logger: (msg: string) => void;
declare const urlToBase64: (url: string) => Promise<string>;
declare const pollTask: (fn: () => Promise<PollResult>, interval?: number, timeout?: number) => Promise<PollResult>;
declare const zipImage: (base64: string, size: number) => Promise<string>;
declare const createOpenAI: any;
declare const exports: {
 vendor: VendorConfig;
 textRequest: (m: TextModel, t: boolean, tl: 0 | 1 | 2 | 3) => any;
 imageRequest: (c: ImageConfig, m: ImageModel) => Promise<string>;
 videoRequest: (c: VideoConfig, m: VideoModel) => Promise<string>;
 ttsRequest: (c: TTSConfig, m: TTSModel) => Promise<string>;
 checkForUpdates?: () => Promise<{ hasUpdate: boolean; latestVersion: string; notice: string }>;
 updateVendor?: () => Promise<string>;
};

// ============================================================
// 供应商配置
// ============================================================

const vendor: VendorConfig = {
 id: "coldsand",
 version: "2.0",
 author: "sand",
 name: "云帧API",
 description: "云帧API模型聚合服务，提供图片生成、视频生成等能力。",
 icon: "",
 inputs: [
 { key: "apiKey", label: "API密钥", type: "password", required: true, placeholder: "灵创AI API Key (sk-...)" },
 { key: "baseUrl", label: "请求地址", type: "url", required: true, placeholder: "以/v1结束，示例：https://grok.285my.cn/v1" },
 ],
 inputValues: {
 apiKey: "",
 baseUrl: "https://coldsand.xyz/v1",
 },
 models: [
 // ===================== 图片生成模型 (/v1/videos, seconds=5) =====================
 {
 name: "GPT Image 2.0 (1K)",
 modelName: "gpt-image-2.0-1k-yunzhen",
 type: "image",
 mode: ["text", "singleImage", "multiReference"],
 associationSkills: "尺寸用WxH格式，如1024x1024",
 },
 {
 name: "GPT Image 2.0 (2K)",
 modelName: "gpt-image-2.0-2k-yunzhen",
 type: "image",
 mode: ["text", "singleImage", "multiReference"],
 associationSkills: "尺寸用WxH格式，如2048x2048",
 },
 {
 name: "GPT Image 2.0 (4K)",
 modelName: "gpt-image-2.0-4k-yunzhen",
 type: "image",
 mode: ["text", "singleImage", "multiReference"],
 associationSkills: "尺寸用WxH格式，如4096x4096",
 },
 {
 name: "GPT Image 2.0 (VV)",
 modelName: "gpt-image-2.0-vv-yunzhen",
 type: "image",
 mode: ["text", "singleImage", "multiReference"],
 associationSkills: "支持多图参考",
 },
 {
 name: "Nano Banana VV 2",
 modelName: "nano-banana-vv-2-yunzhen",
 type: "image",
 mode: ["text", "singleImage"],
 associationSkills: "尺寸用标签: 512p/720p/1k/2k",
 },
 {
 name: "Nano Banana VV 2 (4K)",
 modelName: "nano-banana-vv-2-4k-yunzhen",
 type: "image",
 mode: ["text", "singleImage"],
 associationSkills: "尺寸用标签: 512p/720p/1k/2k",
 },
 {
 name: "Nano Banana VV Pro",
 modelName: "nano-banana-vv-pro-yunzhen",
 type: "image",
 mode: ["text", "singleImage"],
 associationSkills: "尺寸用标签: 512p/720p/1k/2k",
 },
 {
 name: "Nano Banana VV Pro (4K)",
 modelName: "nano-banana-vv-pro-4k-yunzhen",
 type: "image",
 mode: ["text", "singleImage"],
 associationSkills: "尺寸用标签: 512p/720p/1k/2k",
 },
 {
 name: "Gemini 3.1 Flash",
 modelName: "gemini-3.1-flash-yunzhen",
 type: "image",
 mode: ["text", "singleImage", "multiReference"],
 associationSkills: "尺寸用标签: 512p/720p/1k/2k",
 },

 // ===================== 视频生成模型 (/v1/videos) =====================
 {
 name: "Grok Video",
 modelName: "grok-video-yunzhen",
 type: "video",
 mode: ["text", "singleImage", ["imageReference:9"]],
 associationSkills: "多图参考、快速出视频",
 audio: true,
 durationResolutionMap: [{ duration: [6, 10, 15], resolution: ["720p"] }],
 },
 {
 name: "Hailuo VV (720p)",
 modelName: "hailuo-vv-720p-yunzhen",
 type: "video",
 mode: ["text", "singleImage"],
 associationSkills: "低价模型",
 audio: false,
 durationResolutionMap: [{ duration: [6, 10], resolution: ["720p"] }],
 },
 {
 name: "Seedance 1.5 Pro VV (720p)",
 modelName: "seedance-1.5-pro-vv-720p-yunzhen",
 type: "video",
 mode: ["text", "singleImage", "startFrameOptional", ["imageReference:9", "videoReference:3", "audioReference:3"]],
 associationSkills: "音画同生",
 audio: "optional",
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["720p"] }],
 },
 {
 name: "Seedance 2.0 Apimart Fast (480p)",
 modelName: "seedance-2.0-apimart-fast-480p-yunzhen",
 type: "video",
 mode: ["text", "singleImage", "startFrameOptional"],
 audio: false,
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], resolution: ["480p"] }],
 },
 {
 name: "Seedance 2.0 Apimart Fast (720p)",
 modelName: "seedance-2.0-apimart-fast-720p-yunzhen",
 type: "video",
 mode: ["text", "singleImage", "startFrameOptional"],
 audio: false,
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], resolution: ["720p"] }],
 },
 {
 name: "Seedance 2.0 Apimart Full (480p)",
 modelName: "seedance-2.0-apimart-full-480p-yunzhen",
 type: "video",
 mode: ["text", "singleImage", "startFrameOptional", ["imageReference:9", "videoReference:3", "audioReference:3"]],
 associationSkills: "音画同生",
 audio: "optional",
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], resolution: ["480p"] }],
 },
 {
 name: "Seedance 2.0 Apimart Full (720p)",
 modelName: "seedance-2.0-apimart-full-720p-yunzhen",
 type: "video",
 mode: ["text", "singleImage", "startFrameOptional", ["imageReference:9", "videoReference:3", "audioReference:3"]],
 associationSkills: "音画同生",
 audio: "optional",
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], resolution: ["720p"] }],
 },
 {
 name: "Sora 2 VV",
 modelName: "sora2-vv-yunzhen",
 type: "video",
 mode: ["text", "singleImage", ["imageReference:9"]],
 audio: "optional",
 durationResolutionMap: [{ duration: [4, 8, 12], resolution: ["720p", "1080p"] }],
 },
 {
 name: "Vidu Q3 Mini VV (720p)",
 modelName: "vidu-q3-min-vv-720p-yunzhen",
 type: "video",
 mode: ["text", "singleImage", ["imageReference:9"]],
 associationSkills: "低价模型",
 audio: false,
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8, 9, 10], resolution: ["720p"] }],
 },
 {
 name: "Vidu Q3 Pro VV (720p)",
 modelName: "vidu-q3-pro-vv-720p-yunzhen",
 type: "video",
 mode: ["text", "singleImage", ["imageReference:9"]],
 associationSkills: "低价模型",
 audio: false,
 durationResolutionMap: [{ duration: [6, 7, 8, 9, 10], resolution: ["720p"] }],
 },
 {
 name: "ZS Video",
 modelName: "cold-video-yunzhen",
 type: "video",
 mode: ["text", "singleImage"],
 associationSkills: "低价模型",
 audio: false,
 durationResolutionMap: [{ duration: [5, 10, 15], resolution: ["720p"] }],
 },
 {
 name: "PHVer Video",
 modelName: "csand-video-yunzhen",
 type: "video",
 mode: ["text", "singleImage", ["imageReference:9"]],
 audio: false,
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8, 9, 10, 11, 12], resolution: ["720p", "1080p"] }],
 },
 {
 name: "VV Pro",
 modelName: "sand-pro-yunzhen",
 type: "video",
 mode: ["text", "singleImage"],
 associationSkills: "低价模型",
 audio: false,
 durationResolutionMap: [{ duration: [4, 5, 6, 7, 8], resolution: ["480p", "720p"] }],
 },
 ],
};

// ============================================================
// 辅助工具
// ============================================================

const getBaseUrl = () => {
 const url = vendor.inputValues.baseUrl.replace(/\/+$/, "");
 if (url.endsWith("/v1")) return url.slice(0, -3);
 if (url.endsWith("/v1/")) return url.slice(0, -4);
 return url;
};

const getHeaders = () => {
 if (!vendor.inputValues.apiKey) throw new Error("缺少API Key");
 return {
 "Content-Type": "application/json",
 Authorization: `Bearer ${vendor.inputValues.apiKey.replace(/^Bearer\s+/i, "")}`,
 };
};

/** 通用任务创建+轮询 */
const createTaskAndPoll = async (body: any): Promise<string> => {
 const baseUrl = getBaseUrl();
 const headers = getHeaders();

 logger(`[任务提交] 模型: ${body.model}`);

 const createResponse = await axios.post(`${baseUrl}/v1/videos`, body, { headers });
 const taskId = createResponse.data?.id;

 if (!taskId) {
 throw new Error("任务创建失败：未返回任务ID");
 }

 logger(`[任务创建] ID: ${taskId}`);

 const result = await pollTask(
 async (): Promise<PollResult> => {
 const queryResponse = await axios.get(`${baseUrl}/v1/videos/${taskId}`, { headers });
 const task = queryResponse.data;
 logger(`[任务状态] ${task.status} (${task.progress}%)`);

 switch (task.status) {
 case "completed":
 if (task.video_url) return { completed: true, data: task.video_url };
 return { completed: true, error: "任务成功但未返回URL" };
 case "failed":
 return { completed: true, error: task.error?.message || "任务失败" };
 default:
 return { completed: false };
 }
 },
 5000,
 600000,
 );

 if (result.error) throw new Error(result.error);
 return await urlToBase64(result.data!);
};

/**
 * 根据模型名返回图片size参数
 * GPT系列用 WxH 格式，Nano Banana/Gemini系列用标签格式
 */
const getImageSizeParam = (modelName: string, size: string, aspectRatio: string): string => {
 if (modelName.includes("nano-banana") || modelName.includes("gemini")) {
 const tag = size === "4K" ? "2k" : size === "2K" ? "2k" : "1k";
 return tag;
 }
 const table: Record<string, Record<string, string>> = {
 "1K": { "1:1": "1024x1024", "4:3": "1152x864", "3:4": "864x1152", "16:9": "1280x720", "9:16": "720x1280" },
 "2K": { "1:1": "2048x2048", "16:9": "2848x1600", "9:16": "1600x2848" },
 "4K": { "1:1": "4096x4096", "16:9": "5504x3040", "9:16": "3040x5504" },
 };
 return table[size]?.[aspectRatio] || (size === "1K" ? "1024x1024" : size === "2K" ? "2048x2048" : "4096x4096");
};

// ============================================================
// 适配器函数
// ============================================================

const textRequest = (model: TextModel, think: boolean, thinkLevel: 0 | 1 | 2 | 3) => {
 throw new Error("灵创AI供应商不提供文本对话模型");
};

const imageRequest = async (config: ImageConfig, model: ImageModel): Promise<string> => {
 if (!vendor.inputValues.apiKey) throw new Error("缺少API Key");

 const body: any = {
 model: model.modelName,
 prompt: config.prompt || "",
 aspect_ratio: config.aspectRatio || "1:1",
 seconds: "5",
 size: getImageSizeParam(model.modelName, config.size || "2K", config.aspectRatio || "1:1"),
 };

 if (config.referenceList && config.referenceList.length > 0) {
 // 压缩参考图避免413
 const compressed = await Promise.all(
 config.referenceList.map((img) => zipImage(img.base64, 500))
 );
 body.input_images = compressed;
 }

 return await createTaskAndPoll(body);
};

const videoRequest = async (config: VideoConfig, model: VideoModel): Promise<string> => {
 if (!vendor.inputValues.apiKey) throw new Error("缺少API Key");

 const body: any = {
 model: model.modelName,
 prompt: config.prompt || "",
 aspect_ratio: config.aspectRatio,
 seconds: String(config.duration),
 size: config.resolution || "720p",
 };

 if (config.referenceList) {
 const images = config.referenceList.filter((r) => r.type === "image");
 if (images.length > 0) {
 const compressed = await Promise.all(
 images.map((img) => zipImage(img.base64, 500))
 );
 body.input_images = compressed;
 }
 const audios = config.referenceList.filter((r) => r.type === "audio");
 if (audios.length > 0) body.input_audios = audios.map((audio) => audio.base64);
 }

 return await createTaskAndPoll(body);
};

const ttsRequest = async (config: TTSConfig, model: TTSModel): Promise<string> => {
 return "";
};

const checkForUpdates = async (): Promise<{ hasUpdate: boolean; latestVersion: string; notice: string }> => {
 return { hasUpdate: false, latestVersion: "2.0", notice: "" };
};

const updateVendor = async (): Promise<string> => {
 return "";
};

// ============================================================
// 导出
// ============================================================

exports.vendor = vendor;
exports.textRequest = textRequest;
exports.imageRequest = imageRequest;
exports.videoRequest = videoRequest;
exports.ttsRequest = ttsRequest;
exports.checkForUpdates = checkForUpdates;
exports.updateVendor = updateVendor;

export { };
