/**
 * ERP Error Context Capture
 *
 * Lightweight helper to capture Playwright page state when ERP operations fail.
 * All capture calls are defensive — failures do not propagate to the caller.
 */

import type { Page } from 'playwright'
import fs from 'fs'
import path from 'path'
import { getLogDir } from '../logger/shared'

export interface ErpErrorContext {
  pageUrl?: string
  frameHierarchy?: Array<{ name: string; url: string }>
  targetSelector?: string
  step?: string
  screenshotPath?: string
  orderId?: string
  materialCode?: string
  errorStage?: string
}

/**
 * Sanitize a step name for use as a filename component.
 * Replaces non-alphanumeric characters with underscores and truncates.
 */
function sanitizeForFilename(step: string | undefined): string {
  if (!step) return 'unknown'
  return step.replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 40)
}

/**
 * Capture a screenshot of the page for error diagnostics.
 * Stored as PNG under <logDir>/screenshots/.
 * Defensive: never throws.
 */
async function captureScreenshot(page: Page, step?: string): Promise<string | undefined> {
  try {
    if (page.isClosed()) return undefined

    const screenshotDir = path.join(getLogDir(), 'screenshots')
    fs.mkdirSync(screenshotDir, { recursive: true })

    const now = new Date()
    const timestamp = [
      now.getFullYear(),
      String(now.getMonth() + 1).padStart(2, '0'),
      String(now.getDate()).padStart(2, '0'),
      '_',
      String(now.getHours()).padStart(2, '0'),
      String(now.getMinutes()).padStart(2, '0'),
      String(now.getSeconds()).padStart(2, '0')
    ].join('')

    const filename = `err_${timestamp}_${sanitizeForFilename(step)}.png`
    const filePath = path.join(screenshotDir, filename)

    const buffer = await page.screenshot({ type: 'png', timeout: 5000 })
    fs.writeFileSync(filePath, buffer)

    return filePath
  } catch {
    // screenshot failure must not propagate
    return undefined
  }
}

/**
 * Capture the current state of a Playwright page for error logging.
 * Returns a plain object safe for structured logging.
 *
 * @param page - The Playwright page to inspect
 * @param targetSelector - Optional selector that was being targeted
 * @param step - Optional step name for context
 * @param orderId - Optional order ID for error correlation
 * @param materialCode - Optional material code for error correlation
 * @param stage - Optional stage name (defaults to 'unknown')
 */
export async function capturePageContext(
  page: Page,
  targetSelector?: string,
  step?: string,
  orderId?: string,
  materialCode?: string,
  stage: string = 'unknown'
): Promise<ErpErrorContext> {
  const ctx: ErpErrorContext = {}

  try {
    ctx.pageUrl = page.url()
  } catch {
    // page may be closed or inaccessible
  }

  try {
    const frames = page.frames()
    ctx.frameHierarchy = frames.map((f) => ({ name: f.name(), url: f.url() }))
  } catch {
    // frame enumeration may fail on detached pages
  }

  if (targetSelector) {
    ctx.targetSelector = targetSelector
  }

  if (step) {
    ctx.step = step
  }

  if (orderId) {
    ctx.orderId = orderId
  }

  if (materialCode) {
    ctx.materialCode = materialCode
  }

  ctx.errorStage = stage

  ctx.screenshotPath = await captureScreenshot(page, step)

  return ctx
}
