import { BaseError } from '../errors/base'
import { ErrorCode } from '../errors/codes'

export class ConcurrentAccessError extends BaseError {
  constructor(filePath: string) {
    const msg = `Another process is modifying the file ${filePath}. remove ${filePath}.lock to reset lock.`

    super({
      code: ErrorCode.ClientError,
      message: msg,
      hint: `remove ${filePath}.lock to reset lock.`,
    })
  }
}

type YamlMark = {
  line: number
  column: number
  snippet?: string
}

type YamlParseError = {
  reason?: string
  mark?: YamlMark
  message?: string
}

export class BadYamlFormatError extends BaseError {
  constructor(path: string, raw: string, cause: YamlParseError) {
    const reason = cause.reason ?? cause.message ?? 'invalid YAML'
    const mark = cause.mark
    const where = mark ? ` at line ${mark.line + 1}, column ${mark.column + 1}` : ''
    const snippet = mark?.snippet ?? excerpt(raw, mark)
    const header = `Failed to parse YAML file ${path}: ${reason}${where}.`
    const body = snippet ? `\n\n${snippet}` : ''

    super({
      code: ErrorCode.ClientError,
      message: `${header}${body}`,
      hint: `Fix the YAML syntax in ${path} or remove the file to reset it.`,
    })
  }
}

function excerpt(raw: string, mark: YamlMark | undefined): string {
  if (mark === undefined)
    return ''
  const lines = raw.split('\n')
  const target = mark.line
  if (target < 0 || target >= lines.length)
    return ''
  const start = Math.max(0, target - 2)
  const end = Math.min(lines.length, target + 3)
  const width = String(end).length
  const out: string[] = []
  for (let i = start; i < end; i++) {
    const marker = i === target ? '>' : ' '
    const num = String(i + 1).padStart(width, ' ')
    out.push(`${marker} ${num} | ${lines[i]}`)
    if (i === target)
      out.push(`${' '.repeat(width + 4)}${' '.repeat(mark.column)}^`)
  }
  return out.join('\n')
}
