import { normalizeResponseData, requestJson } from "./request"

const OPEN_API_BASE = import.meta.env.VITE_OPEN_API_BASE || "/openApi"
const MAX_DATA_CHARS = 120000
const MAX_ANSWER_CHARS = 8000
const MAX_DATASETS = 12
const MAX_DATASET_ROWS = 500

function joinBase(path) {
  if (/^https?:\/\//.test(path)) return path
  return `${OPEN_API_BASE}${path.startsWith("/") ? path : `/${path}`}`
}

function unwrapResponse(response) {
  const failed =
    response?.success === false ||
    (response?.code !== undefined && ![0, 200, "0", "200"].includes(response.code))

  if (failed) {
    const error = new Error(response?.message || response?.msg || "HTML界面生成失败")
    error.code = response?.code
    throw error
  }

  return normalizeResponseData(response)
}

export async function generateSmartArtifact({
  question,
  answer = "",
  charts = [],
  datasets = [],
  context = null,
  pagePath = window.location.hash || window.location.pathname,
  pageName = "智慧管理",
} = {}) {
  const dataJson = buildArtifactDataJson({ question, answer, charts, datasets, context })
  const response = await requestJson(joinBase("/ai/artifact/html"), {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      question,
      pagePath,
      pageName,
      dataJson,
    }),
    timeout: 110000,
  }).then(unwrapResponse)

  const provider = String(response?.provider || "")
  const model = String(response?.model || "")
  if (provider.toLowerCase() !== "deepseek" || !model.toLowerCase().startsWith("deepseek-")) {
    throw new Error("HTML界面不是由DeepSeek模型生成，已拒绝展示")
  }

  const html = extractHtml(response?.html || response?.content || response)
  if (!html) {
    throw new Error("代码模型没有返回完整HTML")
  }
  if (isDataDumpArtifactHtml(html)) {
    throw new Error("专题页面仍为原始数据表，已拒绝展示，请重新生成")
  }

  return {
    ...response,
    html,
  }
}

function buildArtifactDataJson({ question, answer, charts, datasets, context }) {
  const payload = {
    question: String(question || "").trim(),
    generatedAt: new Date().toISOString(),
    presentation: {
      format: "business-report",
      requirements: [
        "输出应为业务报告页面，而不是原始数据表或字段清单。",
        "不要直接展示 key、rawValue、areaCode、areaRange 等技术字段名。",
        "页面需包含结论、关键指标、图表化对比、重点对象和工作建议。",
      ],
    },
    answer: String(answer || "").slice(0, MAX_ANSWER_CHARS),
    context: sanitizeContext(context),
    datasets: [
      ...normalizeChartDatasets(charts),
      ...normalizeDatasets(datasets),
    ],
  }
  const serialized = JSON.stringify(payload)
  if (serialized.length > MAX_DATA_CHARS) {
    const error = new Error("汇总数据超过120000字符，请先缩小查询范围")
    error.code = "ARTIFACT_DATA_TOO_LARGE"
    throw error
  }
  return serialized
}

function sanitizeContext(context) {
  if (!context || typeof context !== "object") return null
  const {
    question,
    pageName,
    pagePath,
    scope,
    intents,
    notes,
    warnings,
    insights,
  } = context
  return sanitizeSerializableValue({
    question,
    pageName,
    pagePath,
    scope,
    intents,
    notes,
    warnings,
    insights,
  })
}

function normalizeChartDatasets(charts = []) {
  return (Array.isArray(charts) ? charts : []).slice(0, 6).map((chart, index) => ({
    id: chart?.id || `chart-${index + 1}`,
    title: chart?.title || `统计数据${index + 1}`,
    suggestedView: chart?.type || "bar",
    unit: chart?.unit || "",
    subtitle: chart?.subtitle || "",
    source: chart?.source || {},
    rows: normalizeRows(chart?.rows),
  }))
}

function normalizeDatasets(datasets = []) {
  return (Array.isArray(datasets) ? datasets : []).slice(0, MAX_DATASETS).map((dataset, index) => ({
    id: dataset?.id || `dataset-${index + 1}`,
    title: dataset?.title || dataset?.name || `汇总数据${index + 1}`,
    suggestedView: dataset?.suggestedView || dataset?.type || "auto",
    unit: dataset?.unit || "",
    source: dataset?.source || {},
    rows: normalizeRows(dataset?.rows || dataset?.data || dataset),
  }))
}

function normalizeRows(rows) {
  return (Array.isArray(rows) ? rows : [])
    .slice(0, MAX_DATASET_ROWS)
    .map((row) => sanitizeSerializableValue(row))
}

function sanitizeSerializableValue(value, depth = 0) {
  if (depth > 4 || value === undefined || typeof value === "function") return null
  if (value === null || ["string", "number", "boolean"].includes(typeof value)) return value
  if (Array.isArray(value)) return value.slice(0, 50).map((item) => sanitizeSerializableValue(item, depth + 1))
  if (typeof value === "object") {
    return Object.entries(value).reduce((result, [key, item]) => {
      result[key] = sanitizeSerializableValue(item, depth + 1)
      return result
    }, {})
  }
  return String(value)
}

function extractHtml(content) {
  let html = String(content || "").trim()
  if (html.startsWith("```")) {
    html = html.replace(/^```(?:html)?\s*/i, "").replace(/\s*```$/i, "").trim()
  }
  const startMatch = html.match(/<!doctype\s+html|<html\b/i)
  const endIndex = html.toLowerCase().lastIndexOf("</html>")
  if (startMatch && endIndex >= startMatch.index) {
    html = html.slice(startMatch.index, endIndex + 7)
  }
  return /<html\b/i.test(html) && /<body\b/i.test(html) ? html : ""
}

function isDataDumpArtifactHtml(html) {
  const source = String(html || "")
  const text = source
    .replace(/<[^>]+>/g, " ")
    .replace(/\s+/g, " ")
    .toLowerCase()
  const tableCount = (source.match(/<table\b/gi) || []).length
  const technicalTerms = [
    "rawvalue",
    "areacode",
    "arearange",
    "livestockcapacity",
    "bearingcapacity",
    "overloadrate",
    "dataset",
    " key ",
    " type ",
  ]
  const hitCount = technicalTerms.filter((term) => text.includes(term)).length
  return (tableCount >= 2 && hitCount >= 4) || (tableCount >= 1 && hitCount >= 6)
}
