import fs from 'node:fs/promises'

import {
  BAIDU_BEIJING_TIME_URL,
  DEFAULT_REDEEM_PROOF_MODE,
  type RedeemProofMode,
} from './session-proof-constants.js'
import { captureBeijingTimeProof } from './session-proof-beijing-time.js'
import { showResultDialog, composeProofScreenshot } from './session-proof-renderer.js'
import { resolveRedeemProofMode, shouldCaptureBeijingTimeProof } from './session-proof-mode.js'
import { buildArtifactPaths } from './session-proof-paths.js'
import { writeRedeemResultFile } from './session-proof-result-writer.js'

type BrowserPageLike = {
  evaluate: <T = unknown>(callback: any, arg?: unknown) => Promise<T>
  waitForTimeout: (milliseconds: number) => Promise<void>
  setViewportSize: (viewport: { width: number; height: number }) => Promise<void>
  setContent: (html: string, options?: { waitUntil?: string }) => Promise<unknown>
  goto: (url: string, options?: { waitUntil?: string }) => Promise<unknown>
  screenshot: (options: {
    path: string
    fullPage?: boolean
    clip?: { x: number; y: number; width: number; height: number }
  }) => Promise<unknown>
  content: () => Promise<string>
  close: () => Promise<void>
}

type BrowserContextLike = {
  newPage: () => Promise<BrowserPageLike>
}

type RedeemFinalResult = {
  role?: {
    area?: string
  }
  classification?: {
    success?: boolean
  }
  redeem?: {
    iRet?: number | string
    ret?: number | string
    sMsg?: string
  }
  [key: string]: unknown
}

type RedeemArtifactsInput = {
  browserContext: BrowserContextLike
  page: BrowserPageLike
  sessionDir: string
  sessionId?: string
  activityUrl: string
  code: string
  finalResult: RedeemFinalResult
  attempts?: unknown[]
}

type WriteRedeemArtifactFilesInput = Omit<RedeemArtifactsInput, 'sessionDir'> & {
  outputDir: string
  proofMode?: RedeemProofMode | string
}

type RedeemArtifactsResult = {
  proofMode: RedeemProofMode
  screenshotPath: string
  htmlPath: string
  resultPath: string
}

export async function saveRedeemArtifacts({
  browserContext,
  page,
  sessionDir,
  sessionId,
  activityUrl,
  code,
  finalResult,
  attempts,
}: RedeemArtifactsInput): Promise<RedeemArtifactsResult> {
  return writeRedeemArtifactFiles({
    browserContext,
    page,
    outputDir: sessionDir,
    sessionId,
    activityUrl,
    code,
    finalResult,
    attempts,
    proofMode: resolveRedeemProofMode(),
  })
}

export async function writeRedeemArtifactFiles({
  browserContext,
  page,
  outputDir,
  sessionId = '',
  activityUrl,
  code,
  finalResult,
  attempts,
  proofMode = DEFAULT_REDEEM_PROOF_MODE,
}: WriteRedeemArtifactFilesInput): Promise<RedeemArtifactsResult> {
  const effectiveProofMode = resolveRedeemProofMode(proofMode)
  const {
    redeemPageScreenshotPath,
    beijingTimeScreenshotPath,
    screenshotPath,
    htmlPath,
    resultPath,
  } = buildArtifactPaths(outputDir)

  if (effectiveProofMode === 'off') {
    return {
      proofMode: effectiveProofMode,
      screenshotPath: '',
      htmlPath: '',
      resultPath: '',
    }
  }

  await showResultDialog(page, finalResult.redeem?.sMsg || '兑换完成')

  if (effectiveProofMode === 'basic') {
    await page.screenshot({ path: screenshotPath, fullPage: true })
    await writeRedeemResultFile(resultPath, {
      proofMode: effectiveProofMode,
      sessionId,
      activityUrl,
      code,
      finalResult,
      attempts,
      screenshotPath,
    })

    return {
      proofMode: effectiveProofMode,
      screenshotPath,
      htmlPath: '',
      resultPath,
    }
  }

  await page.screenshot({ path: redeemPageScreenshotPath, fullPage: true })

  let beijingTimeProof: {
    screenshotPath: string
    pageUrl: string
    error?: string
  } = {
    screenshotPath: '',
    pageUrl: BAIDU_BEIJING_TIME_URL,
    error: '',
  }

  if (shouldCaptureBeijingTimeProof(finalResult)) {
    try {
      beijingTimeProof = await captureBeijingTimeProof(browserContext, {
        screenshotPath: beijingTimeScreenshotPath,
      })
      await composeProofScreenshot(browserContext, {
        outputPath: screenshotPath,
        redeemImagePath: redeemPageScreenshotPath,
        timeImagePath: beijingTimeProof.screenshotPath,
        redeemMessage: String(finalResult.redeem?.sMsg || '兑换完成'),
        timePageUrl: beijingTimeProof.pageUrl,
      })
    } catch (error) {
      beijingTimeProof = {
        screenshotPath: '',
        pageUrl: BAIDU_BEIJING_TIME_URL,
        error: error instanceof Error ? error.message : '北京时间截图生成失败',
      }
      await fs.copyFile(redeemPageScreenshotPath, screenshotPath)
    }
  } else {
    await fs.copyFile(redeemPageScreenshotPath, screenshotPath)
  }

  await fs.writeFile(htmlPath, await page.content(), 'utf8')
  await writeRedeemResultFile(resultPath, {
    proofMode: effectiveProofMode,
    sessionId,
    activityUrl,
    code,
    finalResult,
    attempts,
    screenshotPath,
    htmlPath,
    redeemPageScreenshotPath,
    beijingTimeScreenshotPath: beijingTimeProof.screenshotPath || '',
    beijingTimePageUrl: beijingTimeProof.pageUrl,
    beijingTimeError: beijingTimeProof.error || '',
  })

  return {
    proofMode: effectiveProofMode,
    screenshotPath,
    htmlPath,
    resultPath,
  }
}

export { resolveRedeemProofMode, shouldCaptureBeijingTimeProof }
