/**
 * 增强版截图服务
 * 结合多种技术方案确保能够成功捕获页面截图
 */

export interface ScreenshotOptions {
  format?: "png" | "jpeg" | "webp"
  quality?: number
  scale?: number
  backgroundColor?: string
  timeout?: number
  width?: number
  height?: number
}

export interface ScreenshotResult {
  success: boolean
  dataUrl?: string
  error?: string
  method?: string
}

class ScreenshotService {
  async captureViewport(options: ScreenshotOptions = {}): Promise<ScreenshotResult> {
    try {
      // 方法1: 使用 html2canvas
      if (typeof window !== "undefined" && window.html2canvas) {
        const canvas = await window.html2canvas(document.body, {
          backgroundColor: options.backgroundColor || "#ffffff",
          scale: options.scale || 1,
          width: options.width,
          height: options.height,
          useCORS: true,
          allowTaint: true,
        })

        const dataUrl = canvas.toDataURL(`image/${options.format || "png"}`, options.quality || 0.9)

        return {
          success: true,
          dataUrl,
          method: "html2canvas",
        }
      }

      // 方法2: 使用 dom-to-image
      if (typeof window !== "undefined" && window.domtoimage) {
        const dataUrl = await window.domtoimage.toPng(document.body, {
          bgcolor: options.backgroundColor || "#ffffff",
          width: options.width,
          height: options.height,
          style: {
            transform: `scale(${options.scale || 1})`,
            transformOrigin: "top left",
          },
        })

        return {
          success: true,
          dataUrl,
          method: "dom-to-image",
        }
      }

      // 方法3: 使用 Canvas API (基础实现)
      const canvas = document.createElement("canvas")
      const ctx = canvas.getContext("2d")

      if (!ctx) {
        throw new Error("无法获取Canvas上下文")
      }

      canvas.width = options.width || window.innerWidth
      canvas.height = options.height || window.innerHeight

      // 设置背景色
      ctx.fillStyle = options.backgroundColor || "#ffffff"
      ctx.fillRect(0, 0, canvas.width, canvas.height)

      // 简单的文本渲染作为占位符
      ctx.fillStyle = "#333333"
      ctx.font = "16px Arial"
      ctx.fillText("页面截图占位符", 50, 50)
      ctx.fillText(`URL: ${window.location.href}`, 50, 80)
      ctx.fillText(`时间: ${new Date().toLocaleString()}`, 50, 110)

      const dataUrl = canvas.toDataURL(`image/${options.format || "png"}`, options.quality || 0.9)

      return {
        success: true,
        dataUrl,
        method: "canvas-fallback",
      }
    } catch (error) {
      console.error("截图失败:", error)
      return {
        success: false,
        error: error instanceof Error ? error.message : "未知错误",
      }
    }
  }

  async captureElement(element: HTMLElement, options: ScreenshotOptions = {}): Promise<ScreenshotResult> {
    try {
      // 使用 html2canvas 截取特定元素
      if (typeof window !== "undefined" && window.html2canvas) {
        const canvas = await window.html2canvas(element, {
          backgroundColor: options.backgroundColor || "#ffffff",
          scale: options.scale || 1,
          width: options.width,
          height: options.height,
          useCORS: true,
          allowTaint: true,
        })

        const dataUrl = canvas.toDataURL(`image/${options.format || "png"}`, options.quality || 0.9)

        return {
          success: true,
          dataUrl,
          method: "html2canvas-element",
        }
      }

      // 使用 dom-to-image 截取特定元素
      if (typeof window !== "undefined" && window.domtoimage) {
        const dataUrl = await window.domtoimage.toPng(element, {
          bgcolor: options.backgroundColor || "#ffffff",
          width: options.width,
          height: options.height,
        })

        return {
          success: true,
          dataUrl,
          method: "dom-to-image-element",
        }
      }

      throw new Error("没有可用的截图库")
    } catch (error) {
      console.error("元素截图失败:", error)
      return {
        success: false,
        error: error instanceof Error ? error.message : "未知错误",
      }
    }
  }
}

export const screenshotService = new ScreenshotService()

// 扩展 Window 接口以包含截图库
declare global {
  interface Window {
    html2canvas?: any
    domtoimage?: any
  }
}

// 动态导入所需库
let htmlToImageModule: any = null
let domToImageModule: any = null

// 加载所需库
async function loadScreenshotLibraries() {
  if (!htmlToImageModule) {
    try {
      htmlToImageModule = await import("html-to-image")
      console.log("html-to-image库加载成功")
    } catch (error) {
      console.warn("html-to-image库加载失败:", error)
    }
  }

  if (!domToImageModule) {
    try {
      domToImageModule = await import("dom-to-image")
      console.log("dom-to-image库加载成功")
    } catch (error) {
      console.warn("dom-to-image库加载失败:", error)
    }
  }

  return {
    htmlToImage: htmlToImageModule,
    domToImage: domToImageModule,
  }
}

/**
 * 使用多种方法尝试捕获页面截图
 * @param targetElement 目标元素（iframe或窗口）
 * @param url 页面URL
 * @param options 配置选项
 * @returns 截图的base64数据URL
 */
export async function captureScreenshot(
  targetElement: HTMLIFrameElement | Window,
  url: string,
  options: {
    maxRetries?: number
    retryDelay?: number
    useDirectCapture?: boolean
    useWindowOpen?: boolean
  } = {},
): Promise<string> {
  const { maxRetries = 3, retryDelay = 1000, useDirectCapture = true, useWindowOpen = false } = options

  let lastError: any = null

  // 尝试多种方法捕获截图
  for (let retry = 0; retry < maxRetries; retry++) {
    try {
      // 如果重试，等待一段时间
      if (retry > 0) {
        await new Promise((resolve) => setTimeout(resolve, retryDelay))
        console.log(`尝试第 ${retry + 1} 次捕获截图...`)
      }

      // 方法1: 使用html-to-image或dom-to-image库
      if (useDirectCapture) {
        const libraries = await loadScreenshotLibraries()

        // 确定目标元素
        let element: HTMLElement | null = null

        if (targetElement instanceof HTMLIFrameElement) {
          try {
            // 尝试访问iframe内容
            const iframeDocument = targetElement.contentDocument || targetElement.contentWindow?.document
            if (iframeDocument) {
              element = iframeDocument.documentElement
            }
          } catch (error) {
            console.warn("无法访问iframe内容，可能是跨域限制:", error)
          }
        } else if (targetElement instanceof Window) {
          element = targetElement.document.documentElement
        }

        if (element) {
          // 尝试使用html-to-image
          if (libraries.htmlToImage) {
            try {
              console.log("使用html-to-image捕获截图...")
              const dataUrl = await libraries.htmlToImage.toPng(element, {
                quality: options.quality || 0.95,
                cacheBust: true,
                pixelRatio: options.scale || 2,
                skipAutoScale: true,
                style: {
                  "background-color": options.backgroundColor || "#ffffff",
                },
              })
              if (dataUrl && dataUrl.startsWith("data:image/png;base64,")) {
                console.log("html-to-image捕获成功!")
                return dataUrl
              }
            } catch (error) {
              console.warn("html-to-image捕获失败:", error)
            }
          }

          // 尝试使用dom-to-image
          if (libraries.domToImage) {
            try {
              console.log("使用dom-to-image捕获截图...")
              const dataUrl = await libraries.domToImage.toPng(element, {
                quality: options.quality || 0.95,
                bgcolor: options.backgroundColor || "#ffffff",
                scale: options.scale || 2,
              })
              if (dataUrl && dataUrl.startsWith("data:image/png;base64,")) {
                console.log("dom-to-image捕获成功!")
                return dataUrl
              }
            } catch (error) {
              console.warn("dom-to-image捕获失败:", error)
            }
          }
        }
      }

      // 方法2: 使用Canvas API
      try {
        console.log("使用Canvas API捕获截图...")
        const screenshot = await captureWithCanvas(targetElement)
        if (screenshot) {
          console.log("Canvas API捕获成功!")
          return screenshot
        }
      } catch (error) {
        console.warn("Canvas API捕获失败:", error)
        lastError = error
      }

      // 方法3: 使用postMessage通信
      if (targetElement instanceof HTMLIFrameElement) {
        try {
          console.log("使用postMessage尝试捕获截图...")
          const screenshot = await captureWithPostMessage(targetElement)
          if (screenshot) {
            console.log("postMessage捕获成功!")
            return screenshot
          }
        } catch (error) {
          console.warn("postMessage捕获失败:", error)
          lastError = error
        }
      }

      // 方法4: 使用window.open打开页面
      if (useWindowOpen) {
        try {
          console.log("使用window.open尝试捕获截图...")
          const screenshot = await captureWithWindowOpen(url)
          if (screenshot) {
            console.log("window.open捕获成功!")
            return screenshot
          }
        } catch (error) {
          console.warn("window.open捕获失败:", error)
          lastError = error
        }
      }
    } catch (error) {
      console.error(`第 ${retry + 1} 次捕获截图失败:`, error)
      lastError = error
    }
  }

  // 所有方法都失败，使用备用方案
  console.warn("所有截图方法都失败，使用备用方案")
  return createFallbackScreenshot(url, lastError)
}

/**
 * 使用Canvas API捕获截图
 */
async function captureWithCanvas(target: HTMLIFrameElement | Window): Promise<string | null> {
  try {
    let document: Document | null = null
    let width = 1200
    let height = 800

    if (target instanceof HTMLIFrameElement) {
      if (!target.contentDocument && !target.contentWindow?.document) {
        throw new Error("无法访问iframe内容")
      }
      document = target.contentDocument || target.contentWindow?.document || null
      width = target.offsetWidth || width
      height = target.offsetHeight || height
    } else {
      document = target.document
      width = target.innerWidth
      height = target.innerHeight
    }

    if (!document) {
      throw new Error("无法获取文档对象")
    }

    // 创建canvas
    const canvas = document.createElement("canvas")
    canvas.width = width
    canvas.height = height

    const ctx = canvas.getContext("2d")
    if (!ctx) {
      throw new Error("无法创建canvas上下文")
    }

    // 绘制白色背景
    ctx.fillStyle = "#ffffff"
    ctx.fillRect(0, 0, width, height)

    // 创建一个图像对象
    const img = new Image()
    img.crossOrigin = "anonymous"

    // 将文档转换为SVG数据URL
    const data = new XMLSerializer().serializeToString(document.documentElement)
    const svg = new Blob([data], { type: "image/svg+xml" })
    const svgUrl = URL.createObjectURL(svg)

    // 等待图像加载
    await new Promise((resolve, reject) => {
      img.onload = resolve
      img.onerror = reject
      img.src = svgUrl
    })

    // 绘制图像
    ctx.drawImage(img, 0, 0, width, height)
    URL.revokeObjectURL(svgUrl)

    // 返回数据URL
    return canvas.toDataURL("image/png")
  } catch (error) {
    console.error("Canvas捕获失败:", error)
    return null
  }
}

/**
 * 使用postMessage与iframe通信捕获截图
 */
async function captureWithPostMessage(iframe: HTMLIFrameElement): Promise<string | null> {
  return new Promise((resolve, reject) => {
    // 设置超时
    const timeout = setTimeout(() => {
      window.removeEventListener("message", messageHandler)
      reject(new Error("postMessage截图超时"))
    }, options.timeout || 5000)

    // 消息处理函数
    function messageHandler(event: MessageEvent) {
      if (event.data && event.data.type === "screenshot" && event.data.dataUrl) {
        clearTimeout(timeout)
        window.removeEventListener("message", messageHandler)
        resolve(event.data.dataUrl)
      }
    }

    // 监听消息
    window.addEventListener("message", messageHandler)

    // 向iframe发送消息
    try {
      iframe.contentWindow?.postMessage({ type: "requestScreenshot" }, "*")
    } catch (error) {
      clearTimeout(timeout)
      window.removeEventListener("message", messageHandler)
      reject(error)
    }
  })
}

/**
 * 使用window.open打开页面并捕获截图
 */
async function captureWithWindowOpen(url: string): Promise<string | null> {
  return new Promise((resolve, reject) => {
    try {
      // 打开新窗口
      const newWindow = window.open(url, "_blank", "width=1200,height=800")

      if (!newWindow) {
        reject(new Error("无法打开新窗口，可能被浏览器阻止"))
        return
      }

      // 设置超时
      const timeout = setTimeout(() => {
        if (newWindow) newWindow.close()
        reject(new Error("window.open截图超时"))
      }, 10000)

      // 等待页面加载完成
      newWindow.onload = async () => {
        try {
          // 等待一段时间，确保页面完全渲染
          await new Promise((resolve) => setTimeout(resolve, 2000))

          // 尝试捕获截图
          const libraries = await loadScreenshotLibraries()
          let screenshot = null

          if (libraries.htmlToImage) {
            try {
              screenshot = await libraries.htmlToImage.toPng(newWindow.document.documentElement)
            } catch (error) {
              console.warn("html-to-image捕获失败:", error)
            }
          }

          if (!screenshot && libraries.domToImage) {
            try {
              screenshot = await libraries.domToImage.toPng(newWindow.document.documentElement)
            } catch (error) {
              console.warn("dom-to-image捕获失败:", error)
            }
          }

          // 关闭窗口
          newWindow.close()
          clearTimeout(timeout)

          if (screenshot) {
            resolve(screenshot)
          } else {
            reject(new Error("无法捕获新窗口的截图"))
          }
        } catch (error) {
          newWindow.close()
          clearTimeout(timeout)
          reject(error)
        }
      }

      // 处理加载错误
      newWindow.onerror = (event) => {
        newWindow.close()
        clearTimeout(timeout)
        reject(new Error("新窗口加载出错"))
      }
    } catch (error) {
      reject(error)
    }
  })
}

/**
 * 创建备用截图
 * 当所有方法都失败时，生成一个包含页面信息的模拟截图
 */
function createFallbackScreenshot(url: string, error: any): string {
  // 提取页面标题
  const pathParts = url.split("/")
  const pageName = pathParts[pathParts.length - 1] || "页面"

  // 创建canvas
  const canvas = document.createElement("canvas")
  const ctx = canvas.getContext("2d")

  if (!ctx) {
    throw new Error("无法创建canvas上下文")
  }

  // 设置canvas尺寸
  const width = 1200
  const height = 800
  canvas.width = width
  canvas.height = height

  // 绘制背景
  ctx.fillStyle = "#ffffff"
  ctx.fillRect(0, 0, width, height)

  // 绘制边框
  ctx.strokeStyle = "#e5e7eb"
  ctx.lineWidth = 2
  ctx.strokeRect(1, 1, width - 2, height - 2)

  // 绘制页面信息
  ctx.fillStyle = "#f9fafb"
  ctx.fillRect(0, 0, width, 80)

  ctx.fillStyle = "#111827"
  ctx.font = "bold 24px system-ui"
  ctx.fillText(pageName, 20, 40)

  ctx.fillStyle = "#6b7280"
  ctx.font = "14px system-ui"
  ctx.fillText(url, 20, 65)

  // 绘制内容区域
  ctx.fillStyle = "#f3f4f6"
  ctx.fillRect(20, 100, width - 40, height - 120)

  // 添加错误信息
  ctx.fillStyle = "#ef4444"
  ctx.font = "16px system-ui"
  ctx.fillText("截图捕获失败", 40, 140)

  ctx.fillStyle = "#6b7280"
  ctx.font = "14px system-ui"
  ctx.fillText(`错误信息: ${error ? error.message || "未知错误" : "未知错误"}`, 40, 170)
  ctx.fillText(`URL: ${url}`, 40, 200)
  ctx.fillText("请尝试手动截图或刷新页面后重试", 40, 230)

  // 添加水印
  ctx.save()
  ctx.globalAlpha = 0.1
  ctx.fillStyle = "#000000"
  ctx.font = "bold 48px system-ui"
  ctx.translate(width / 2, height / 2)
  ctx.rotate(-Math.PI / 6)
  ctx.textAlign = "center"
  ctx.fillText("备用截图", 0, 0)
  ctx.restore()

  // 返回base64数据
  return canvas.toDataURL("image/png")
}

/**
 * 注入截图脚本到页面
 * 这个函数会向页面注入一个脚本，使页面能够响应截图请求
 */
export function injectScreenshotScript(window: Window): void {
  try {
    const script = window.document.createElement("script")
    script.textContent = `
      // 监听截图请求
      window.addEventListener('message', async function(event) {
        if (event.data && event.data.type === 'requestScreenshot') {
          try {
            // 动态加载html2canvas
            const script = document.createElement('script');
            script.src = 'https://html2canvas.hertzen.com/dist/html2canvas.min.js';
            script.onload = async function() {
              try {
                // 使用html2canvas捕获页面
                const canvas = await html2canvas(document.documentElement, {
                  allowTaint: true,
                  useCORS: true,
                  scale: ${options.scale || 2},
                  backgroundColor: '${options.backgroundColor || "#ffffff"}'
                });
                
                // 发送截图数据
                const dataUrl = canvas.toDataURL('image/${options.format || "png"}', ${options.quality || 0.9});
                window.parent.postMessage({
                  type: 'screenshot',
                  dataUrl: dataUrl
                }, '*');
              } catch (error) {
                console.error('html2canvas捕获失败:', error);
                window.parent.postMessage({
                  type: 'screenshotError',
                  error: error.toString()
                }, '*');
              }
            };
            script.onerror = function(error) {
              console.error('加载html2canvas失败:', error);
              window.parent.postMessage({
                type: 'screenshotError',
                error: 'Failed to load html2canvas'
              }, '*');
            };
            document.head.appendChild(script);
          } catch (error) {
            console.error('处理截图请求时出错:', error);
            window.parent.postMessage({
              type: 'screenshotError',
              error: error.toString()
            }, '*');
          }
        }
      });
      
      console.log('截图脚本已注入');
    `
    window.document.head.appendChild(script)
  } catch (error) {
    console.error("注入截图脚本失败:", error)
  }
}

/**
 * 使用服务器端API捕获截图
 * 注意：这需要后端支持
 */
export async function captureWithServerAPI(url: string): Promise<string | null> {
  try {
    // 这里应该调用后端API
    // 由于我们没有实际的后端API，这里只是一个示例
    console.log("尝试使用服务器端API捕获截图:", url)

    // 模拟API调用
    const response = await fetch("/api/screenshot", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ url }),
    })

    if (!response.ok) {
      throw new Error(`API请求失败: ${response.status} ${response.statusText}`)
    }

    const data = await response.json()
    if (data.success && data.screenshot) {
      return data.screenshot
    } else {
      throw new Error(data.error || "未知错误")
    }
  } catch (error) {
    console.error("服务器端API捕获失败:", error)
    return null
  }
}
