"use client";

import { useState } from "react";
import hljs from "@/lib/hljs";
import "highlight.js/styles/github-dark.css";
import { diffLines } from "diff";
import { Copy, Check } from "lucide-react";
import { getLanguageFromFile, copyToClipboard } from "@/lib/vulnerability-utils";

function safeHighlight(code: string, lang: string): string {
  try {
    return hljs.highlight(code, { language: lang, ignoreIllegals: true }).value;
  } catch {
    return hljs.highlightAuto(code).value;
  }
}

interface CodeDiffBlockProps {
  file: string;
  startLine: number;
  endLine?: number;
  before: string;
  after: string;
  onCopy?: () => void;
}

export function CodeDiffBlock({ file, startLine, endLine, before, after, onCopy }: CodeDiffBlockProps) {
  const [copied, setCopied] = useState(false);

  const lineRef =
    endLine && endLine !== startLine ? `${startLine}-${endLine}` : `${startLine}`;
  const lang = getLanguageFromFile(file) || "text";
  const changes = diffLines(before, after);

  let oldLineNo = startLine;
  let newLineNo = startLine;
  const rows = changes.flatMap((change) =>
    change.value
      .replace(/\n$/, "")
      .split("\n")
      .map((line) => {
        const highlighted =
          line === ""
            ? "\n"
            : lang !== "text"
              ? safeHighlight(line, lang)
              : line.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
        let leftNo = "";
        let rightNo = "";
        if (change.removed) {
          leftNo = String(oldLineNo++);
        } else if (change.added) {
          rightNo = String(newLineNo++);
        } else {
          leftNo = String(oldLineNo++);
          rightNo = String(newLineNo++);
        }
        return { highlighted, added: !!change.added, removed: !!change.removed, leftNo, rightNo };
      })
  );

  const copy = () => {
    copyToClipboard(after);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
    onCopy?.();
  };

  return (
    <div className="rounded-md border border-[#2a2a2a] overflow-hidden">
      <div className="flex items-stretch">
        <span className="relative flex items-center text-[13px] text-[#999] font-mono px-4 py-2 border-r border-[#2a2a2a] break-all">
          {file}:{lineRef}
          <span className="absolute top-0 inset-x-0 h-0.5 bg-white/60 rounded-full" />
        </span>
        <div className="flex-1 border-b border-[#2a2a2a]" />
        <button
          onClick={copy}
          className="px-3 py-2 text-[#555] hover:text-white transition-colors flex-shrink-0 border-b border-[#2a2a2a]"
          aria-label="Copy fixed code"
        >
          {copied ? (
            <Check className="w-3.5 h-3.5 text-emerald-400" />
          ) : (
            <Copy className="w-3.5 h-3.5" />
          )}
        </button>
      </div>
      <div className="overflow-auto max-h-[400px]">
        <table className="w-full border-collapse font-mono text-[12px] leading-[22px] [font-variant-ligatures:none]">
          <tbody>
            {rows.map((row, i) => (
              <tr
                key={i}
                className={row.added ? "bg-blue-500/[0.12]" : row.removed ? "bg-red-500/[0.12]" : ""}
              >
                <td className="select-none w-[1px] whitespace-nowrap pl-4 pr-1.5 text-right text-[#555] align-top text-[12px] leading-[22px]">
                  {row.leftNo}
                </td>
                <td className="select-none w-[1px] whitespace-nowrap pl-1.5 pr-4 text-right text-[#555] align-top text-[12px] leading-[22px] border-r border-[#2a2a2a]">
                  {row.rightNo}
                </td>
                <td
                  className="pl-4 pr-4 whitespace-pre"
                  dangerouslySetInnerHTML={{ __html: row.highlighted }}
                />
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
