import { BackportPatchKind } from '@/lib/backport-types'

export interface ParsedPatchHunk {
  id: string
  fileId: string
  filePath: string
  header: string
  lineIndex: number
}

export interface ParsedPatchFile {
  id: string
  kind: BackportPatchKind
  path: string
  oldPath: string
  newPath: string
  additions: number
  deletions: number
  hunkIds: string[]
}

export interface ParsedPatchSummary {
  kind: BackportPatchKind
  files: ParsedPatchFile[]
  hunks: ParsedPatchHunk[]
  additions: number
  deletions: number
  lineCount: number
  rawLines: string[]
}

function normalizePatchPath(value: string): string {
  return value.replace(/^(a|b)\//, '').trim()
}

function extractPatchPath(line: string, prefix: string): string {
  if (!line.startsWith(prefix)) return ''
  const raw = line.slice(prefix.length).trim()
  if (raw === '/dev/null') return raw
  return normalizePatchPath(raw)
}

export function parseUnifiedDiff(kind: BackportPatchKind, patchText: string): ParsedPatchSummary {
  const rawLines = patchText.split(/\r?\n/)
  const files: ParsedPatchFile[] = []
  const hunks: ParsedPatchHunk[] = []
  let totalAdditions = 0
  let totalDeletions = 0
  let currentFile: ParsedPatchFile | null = null

  const ensureCurrentFile = (fallbackPath = 'unknown-file'): ParsedPatchFile => {
    if (currentFile) return currentFile
    currentFile = {
      id: `patch-file-${files.length}`,
      kind,
      path: fallbackPath,
      oldPath: '',
      newPath: '',
      additions: 0,
      deletions: 0,
      hunkIds: [],
    }
    files.push(currentFile)
    return currentFile
  }

  for (const [lineIndex, line] of rawLines.entries()) {
    if (line.startsWith('diff --git ')) {
      const match = /^diff --git a\/(.+?) b\/(.+)$/.exec(line)
      const filePath = normalizePatchPath(
        match?.[2] || match?.[1] || `unknown-file-${files.length + 1}`
      )
      currentFile = {
        id: `patch-file-${files.length}`,
        kind,
        path: filePath,
        oldPath: match?.[1] ? normalizePatchPath(match[1]) : '',
        newPath: match?.[2] ? normalizePatchPath(match[2]) : '',
        additions: 0,
        deletions: 0,
        hunkIds: [],
      }
      files.push(currentFile)
      continue
    }

    if (line.startsWith('--- ')) {
      const file = ensureCurrentFile()
      file.oldPath = extractPatchPath(line, '--- ')
      if (!file.path || file.path.startsWith('unknown-file')) {
        file.path = file.oldPath === '/dev/null' ? file.path : file.oldPath
      }
      continue
    }

    if (line.startsWith('+++ ')) {
      const file = ensureCurrentFile()
      file.newPath = extractPatchPath(line, '+++ ')
      if (!file.path || file.path.startsWith('unknown-file')) {
        file.path = file.newPath === '/dev/null' ? file.path : file.newPath
      }
      continue
    }

    if (line.startsWith('@@')) {
      const file = ensureCurrentFile()
      const hunkId = `${file.id}-hunk-${file.hunkIds.length + 1}`
      file.hunkIds.push(hunkId)
      hunks.push({
        id: hunkId,
        fileId: file.id,
        filePath: file.path,
        header: line.trim(),
        lineIndex,
      })
      continue
    }

    if (line.startsWith('+') && !line.startsWith('+++')) {
      const file = ensureCurrentFile()
      file.additions += 1
      totalAdditions += 1
      continue
    }

    if (line.startsWith('-') && !line.startsWith('---')) {
      const file = ensureCurrentFile()
      file.deletions += 1
      totalDeletions += 1
    }
  }

  return {
    kind,
    files,
    hunks,
    additions: totalAdditions,
    deletions: totalDeletions,
    lineCount: rawLines.length,
    rawLines,
  }
}

export type PatchLineType = 'meta' | 'file' | 'hunk' | 'add' | 'remove' | 'context'

export function classifyPatchLine(line: string): PatchLineType {
  if (!line) return 'context'
  if (
    line.startsWith('diff --git ') ||
    line.startsWith('index ') ||
    line.startsWith('new file mode ') ||
    line.startsWith('deleted file mode ') ||
    line.startsWith('similarity index ') ||
    line.startsWith('rename from ') ||
    line.startsWith('rename to ')
  ) {
    return 'meta'
  }
  if (line.startsWith('--- ') || line.startsWith('+++ ')) return 'file'
  if (line.startsWith('@@')) return 'hunk'
  if (line.startsWith('+') && !line.startsWith('+++')) return 'add'
  if (line.startsWith('-') && !line.startsWith('---')) return 'remove'
  return 'context'
}

export function getLightPatchLineClass(lineType: PatchLineType): string {
  if (lineType === 'meta') return 'bg-slate-100 text-slate-700'
  if (lineType === 'file') return 'bg-blue-50 text-blue-800'
  if (lineType === 'hunk') return 'bg-slate-50 text-slate-500'
  if (lineType === 'add') return 'bg-emerald-50 text-emerald-900'
  if (lineType === 'remove') return 'bg-red-50 text-red-900'
  return 'bg-white text-slate-800'
}