import { resolveLlmRuntimeConfig, type ResolvedLlmRuntimeConfig } from "./standardization-llm.ts";
import { runWithLlmDebugLog } from "../core/llm-debug-log.js";

export type BigModelFileObject = {
  id: string;
  object?: string;
  bytes?: number;
  created_at?: number;
  filename?: string;
  purpose?: string;
};

export type BigModelBatchStatus =
  | "validating"
  | "failed"
  | "in_progress"
  | "finalizing"
  | "completed"
  | "expired"
  | "cancelling"
  | "cancelled"
  | string;

export type BigModelBatchRecord = {
  id: string;
  object?: string;
  endpoint?: string;
  input_file_id?: string;
  completion_window?: string;
  status: BigModelBatchStatus;
  output_file_id?: string;
  error_file_id?: string;
  created_at?: number;
  in_progress_at?: number;
  finalizing_at?: number;
  completed_at?: number;
  failed_at?: number;
  expired_at?: number;
  cancelling_at?: number;
  cancelled_at?: number;
  total?: number;
  completed?: number;
  failed?: number;
  metadata?: Record<string, string> | null;
};

type BatchMetadata = Record<string, string>;

const BIGMODEL_BATCH_SUPPORTED_MODELS = new Set([
  "glm-4",
  "glm-4-0520",
  "glm-4-plus",
  "glm-4-long",
  "glm-4-plus-0111",
  "glm-4-air",
  "glm-4-air-0111",
  "glm-4-air-250414",
  "glm-4-flash",
  "glm-4-flashx-250414",
  "glm-3-turbo",
  "glm-4v",
  "glm-4v-plus",
  "glm-4v-plus-0111",
]);
export const FIXED_BIGMODEL_BATCH_MODEL = "glm-4-plus";

function normalizeSpace(value: unknown) {
  return String(value ?? "").replace(/\s+/g, " ").trim();
}

function buildAuthHeaders(apiKey: string) {
  return {
    Authorization: `Bearer ${apiKey}`,
  };
}

function isBigModelRuntimeConfig(config: ResolvedLlmRuntimeConfig) {
  return config.provider === "glm" || /bigmodel\.cn/i.test(config.baseURL);
}

export function resolveBigModelBatchModel(value: unknown = process.env.FIXED_SEARCH_LLM_MODEL): string {
  const model = normalizeSpace(value) || FIXED_BIGMODEL_BATCH_MODEL;
  if (!BIGMODEL_BATCH_SUPPORTED_MODELS.has(model)) {
    throw new Error(
      `FIXED_SEARCH_LLM_MODEL=${model} 不受支持；BigModel Batch 支持模型: ${
        Array.from(BIGMODEL_BATCH_SUPPORTED_MODELS).join(", ")
      }`,
    );
  }

  return model;
}

export async function resolveBigModelBatchRuntimeConfig(): Promise<ResolvedLlmRuntimeConfig> {
  const config = await resolveLlmRuntimeConfig("fixed_search_batch");
  if (!isBigModelRuntimeConfig(config)) {
    throw new Error(`离线 Batch 仅支持智谱 BigModel，当前 provider=${config.provider || "unknown"}`);
  }

  return {
    ...config,
    model: resolveBigModelBatchModel(),
  };
}

async function readJsonResponse<T>(response: Response, label: string): Promise<T> {
  const text = await response.text();
  if (!response.ok) {
    throw new Error(`${label} 失败: HTTP ${response.status} ${text}`.trim());
  }

  if (!text.trim()) {
    throw new Error(`${label} 失败: 响应为空`);
  }

  return JSON.parse(text) as T;
}

export async function uploadBatchFile(params: {
  filename: string;
  content: string;
}): Promise<BigModelFileObject> {
  const config = await resolveBigModelBatchRuntimeConfig();
  const form = new FormData();
  form.append("file", new Blob([params.content], { type: "application/jsonl" }), params.filename);
  form.append("purpose", "batch");

  return runWithLlmDebugLog(
    {
      scope: "automation",
      stage: "fixed_search_batch",
      label: "bigmodelBatch.uploadFile",
      provider: config.provider,
      model: config.model,
    },
    {
      endpoint: "/files",
      filename: params.filename,
      contentLength: params.content.length,
      model: config.model,
    },
    async () => {
      const response = await fetch(`${config.baseURL}/files`, {
        method: "POST",
        headers: buildAuthHeaders(config.apiKey),
        body: form,
      });

      return readJsonResponse<BigModelFileObject>(response, "上传 Batch 文件");
    },
  );
}

export async function createBatchTask(params: {
  inputFileId: string;
  endpoint?: "/v4/chat/completions";
  autoDeleteInputFile?: boolean;
  metadata?: BatchMetadata;
}): Promise<BigModelBatchRecord> {
  const config = await resolveBigModelBatchRuntimeConfig();
  const body = {
    input_file_id: params.inputFileId,
    endpoint: params.endpoint ?? "/v4/chat/completions",
    auto_delete_input_file: params.autoDeleteInputFile ?? true,
    metadata: params.metadata ?? null,
  };

  return runWithLlmDebugLog(
    {
      scope: "automation",
      stage: "fixed_search_batch",
      label: "bigmodelBatch.createTask",
      provider: config.provider,
      model: config.model,
    },
    {
      endpoint: "/batches",
      inputFileId: params.inputFileId,
      model: config.model,
      contentLength: JSON.stringify(body).length,
    },
    async () => {
      const response = await fetch(`${config.baseURL}/batches`, {
        method: "POST",
        headers: {
          ...buildAuthHeaders(config.apiKey),
          "Content-Type": "application/json",
        },
        body: JSON.stringify(body),
      });

      return readJsonResponse<BigModelBatchRecord>(response, "创建 Batch 任务");
    },
  );
}

export async function retrieveBatchTask(batchId: string): Promise<BigModelBatchRecord> {
  const config = await resolveBigModelBatchRuntimeConfig();
  return runWithLlmDebugLog(
    {
      scope: "automation",
      stage: "fixed_search_batch",
      label: "bigmodelBatch.retrieveTask",
      provider: config.provider,
      model: config.model,
    },
    {
      endpoint: "/batches/{batchId}",
      batchId,
      model: config.model,
    },
    async () => {
      const response = await fetch(`${config.baseURL}/batches/${batchId}`, {
        method: "GET",
        headers: buildAuthHeaders(config.apiKey),
      });

      return readJsonResponse<BigModelBatchRecord>(response, "查询 Batch 任务");
    },
  );
}

export async function downloadBatchFileContent(fileId: string): Promise<string> {
  const config = await resolveBigModelBatchRuntimeConfig();
  return runWithLlmDebugLog(
    {
      scope: "automation",
      stage: "fixed_search_batch",
      label: "bigmodelBatch.downloadFileContent",
      provider: config.provider,
      model: config.model,
    },
    {
      endpoint: "/files/{fileId}/content",
      inputFileId: fileId,
      model: config.model,
    },
    async () => {
      const response = await fetch(`${config.baseURL}/files/${fileId}/content`, {
        method: "GET",
        headers: buildAuthHeaders(config.apiKey),
      });

      if (!response.ok) {
        const text = await response.text();
        throw new Error(`下载 Batch 文件失败: HTTP ${response.status} ${text}`.trim());
      }

      return response.text();
    },
  );
}
