import { computeLineHash } from "./hash-computation"
import { HASHLINE_REF_PATTERN } from "./constants"

export interface LineRef {
  line: number
  hash: string
}

const LINE_REF_EXTRACT_PATTERN = /([0-9]+#[ZPMQVRWSNKTXJBYH]{2})/

function normalizeLineRef(ref: string): string {
  const trimmed = ref.trim()
  if (HASHLINE_REF_PATTERN.test(trimmed)) {
    return trimmed
  }

  const extracted = trimmed.match(LINE_REF_EXTRACT_PATTERN)
  if (extracted) {
    return extracted[1]
  }

  return trimmed
}

export function parseLineRef(ref: string): LineRef {
  const normalized = normalizeLineRef(ref)
  const match = normalized.match(HASHLINE_REF_PATTERN)
  if (!match) {
    throw new Error(
      `Invalid line reference format: "${ref}". Expected format: "LINE#ID" (e.g., "42#VK")`
    )
  }
  return {
    line: Number.parseInt(match[1], 10),
    hash: match[2],
  }
}

export function validateLineRef(lines: string[], ref: string): void {
  const { line, hash } = parseLineRef(ref)

  if (line < 1 || line > lines.length) {
    throw new Error(
      `Line number ${line} out of bounds. File has ${lines.length} lines.`
    )
  }

  const content = lines[line - 1]
  const currentHash = computeLineHash(line, content)

  if (currentHash !== hash) {
    throw new Error(
      `Hash mismatch at line ${line}. Expected hash: ${hash}, current hash: ${currentHash}. ` +
        `Line content may have changed. Current content: "${content}"`
    )
  }
}

export function validateLineRefs(lines: string[], refs: string[]): void {
  const mismatches: string[] = []

  for (const ref of refs) {
    const { line, hash } = parseLineRef(ref)

    if (line < 1 || line > lines.length) {
      mismatches.push(`Line number ${line} out of bounds (file has ${lines.length} lines)`) 
      continue
    }

    const content = lines[line - 1]
    const currentHash = computeLineHash(line, content)
    if (currentHash !== hash) {
      mismatches.push(
        `line ${line}: expected ${hash}, current ${currentHash} (${line}#${currentHash}) content: "${content}"`
      )
    }
  }

  if (mismatches.length > 0) {
    throw new Error(`Hash mismatches:\n- ${mismatches.join("\n- ")}`)
  }
}
