"use client";

import { useState } from "react";
import { Clock, Globe, ChevronDown } from "lucide-react";
import { parseTarget } from "@/lib/target-utils";
import { ProviderIcon } from "@/components/AddRepositoryDialog";
import { getSeverityDot } from "@/lib/vulnerability-utils";
import { formatTimeAgo } from "@/lib/utils";
import { FIX_EFFORT_META, type FixEffort, type Vulnerability } from "@/types/issues";

/* ─── Human-friendly CVSS labels ─── */

const HUMAN_LABELS: Record<string, Record<string, string>> = {
  attack_vector: { N: "Remotely exploitable", A: "Adjacent network", L: "Local access required", P: "Physical access required" },
  attack_complexity: { L: "Easy to exploit", H: "Requires specific conditions" },
  privileges_required: { N: "No authentication needed", L: "Low privileges needed", H: "High privileges needed" },
  user_interaction: { N: "No user action required", R: "Requires user action", P: "Passive user role", A: "Active user role" },
  scope: { U: "Impact stays contained", C: "Can spread to other systems" },
  confidentiality: { N: "No data exposure", L: "Partial data exposure", H: "Full data exposure" },
  integrity: { N: "No data modification", L: "Limited modification", H: "Full data modification" },
  availability: { N: "No service disruption", L: "Limited disruption", H: "Full service disruption" },
};

const RISK_LEVEL: Record<string, Record<string, "low" | "medium" | "high">> = {
  attack_vector: { N: "high", A: "medium", L: "low", P: "low" },
  attack_complexity: { L: "high", H: "low" },
  privileges_required: { N: "high", L: "medium", H: "low" },
  user_interaction: { N: "high", R: "low", P: "medium", A: "low" },
  scope: { C: "high", U: "low" },
  confidentiality: { H: "high", L: "medium", N: "low" },
  integrity: { H: "high", L: "medium", N: "low" },
  availability: { H: "high", L: "medium", N: "low" },
};

const RISK_BADGE: Record<string, string> = {
  high: "bg-red-500/15 text-red-400 border-red-500/25",
  medium: "bg-yellow-500/15 text-yellow-400 border-yellow-500/25",
  low: "bg-[#222] text-[#666] border-[#333]",
};

const FACTOR_GROUPS: { label: string; keys: string[] }[] = [
  { label: "Exploitability", keys: ["attack_vector", "attack_complexity", "privileges_required", "user_interaction"] },
  { label: "Impact", keys: ["scope", "confidentiality", "integrity", "availability"] },
];

/* ─── Location link builder ─── */

export function buildLocationHref(
  repoUrl: string,
  provider: string,
  branch: string,
  file: string,
  startLine: number,
): string | null {
  const base = repoUrl.replace(/\.git$/, "").replace(/\/+$/, "");
  const encodedFile = file.split("/").map(encodeURIComponent).join("/");
  const encodedBranch = branch.split("/").map(encodeURIComponent).join("/");

  if (provider === "github") {
    return `${base}/blob/${encodedBranch}/${encodedFile}#L${startLine}`;
  }
  if (provider === "gitlab") {
    return `${base}/-/blob/${encodedBranch}/${encodedFile}#L${startLine}`;
  }
  return null;
}

/* ─── Props ─── */

interface IssueSidebarProps {
  vulnerability: Vulnerability;
  statusSlot: React.ReactNode;
  slackThreadUrl?: string | null;
}

/* ─── Component ─── */

export function IssueSidebar({ vulnerability, statusSlot, slackThreadUrl }: IssueSidebarProps) {
  const { severity, cvss, cve, cwe, fix_effort, created_at, target, endpoint, method, code_locations, cvss_breakdown, location_meta } = vulnerability;

  const [riskOpen, setRiskOpen] = useState(true);

  const fixLocations = code_locations?.filter((loc) => loc.fix_before && loc.fix_after);
  const hasLocations = fixLocations && fixLocations.length > 0;
  const parsed = target ? parseTarget(target) : null;
  const hasAsset = !!(target || endpoint || method || hasLocations);

  const hasBreakdown = cvss_breakdown && Object.values(cvss_breakdown).some((v) => v != null);

  return (
    <aside className="lg:sticky lg:top-6 lg:max-h-[calc(100vh-3rem)] lg:overflow-y-auto">
      {/* ─── Metadata ─── */}
      <div className="pb-4">
        <div className="space-y-3">
          {/* Severity */}
          <div className="flex items-center justify-between">
            <span className="text-xs text-[#aaa]">Severity</span>
            <div className="flex items-center gap-1.5">
              <div className={`w-2 h-2 rounded-full ${getSeverityDot(severity)}`} aria-hidden="true" />
              <span className="text-sm font-medium capitalize text-white">{severity}</span>
            </div>
          </div>

          {/* CVSS */}
          <div className="flex items-center justify-between">
            <span className="text-xs text-[#aaa]">CVSS Score</span>
            <span className="text-sm font-semibold tabular-nums text-white">{cvss !== null ? cvss : "N/A"}</span>
          </div>

          {/* CVE */}
          {cve && (
            <div className="flex items-center justify-between">
              <span className="text-xs text-[#aaa]">CVE</span>
              <span className="text-sm text-white font-mono">{cve}</span>
            </div>
          )}

          {/* CWE */}
          {cwe && cwe.length > 0 && (
            <div className="flex items-center justify-between">
              <span className="text-xs text-[#aaa]">CWE</span>
              <span className="text-xs text-white font-mono truncate max-w-[80%] text-right" title={cwe.join(" · ")}>
                {cwe.join(" · ")}
              </span>
            </div>
          )}

          {/* Fix Effort */}
          {fix_effort && (
            <div className="flex items-center justify-between">
              <span className="text-xs text-[#aaa]">Fix Effort</span>
              <span className={`inline-flex items-center px-2 py-0.5 text-[11px] font-medium rounded-full border ${FIX_EFFORT_META[fix_effort as FixEffort]?.color ?? "text-[#666]"}`}>
                {fix_effort.charAt(0).toUpperCase() + fix_effort.slice(1)}
              </span>
            </div>
          )}

          {/* Discovered */}
          <div className="flex items-center justify-between">
            <span className="text-xs text-[#aaa]">Discovered</span>
            <div className="flex items-center gap-1.5">
              <Clock className="w-3 h-3 text-[#444]" aria-hidden="true" />
              <span className="text-sm text-white">{formatTimeAgo(created_at)}</span>
            </div>
          </div>

          {/* Status */}
          <div className="flex items-center justify-between">
            <span className="text-xs text-[#aaa]">Status</span>
            {statusSlot}
          </div>
        </div>
      </div>

      {/* ─── Asset ─── */}
      {hasAsset && (
        <div className="border-t border-[#191919] pt-4 pb-4">
          <p className="text-xs font-medium text-[#aaa] mb-2.5">Asset</p>
          <div className="space-y-2.5">
            {target && parsed && (
              <div className="flex items-center gap-1.5">
                {parsed.provider ? (
                  <span className="flex-shrink-0 [&_svg]:w-3.5 [&_svg]:h-3.5" aria-hidden="true">
                    <ProviderIcon provider={parsed.provider} />
                  </span>
                ) : (
                  <Globe className="w-3.5 h-3.5 text-[#555] flex-shrink-0" aria-hidden="true" />
                )}
                {parsed.href ? (
                  <a
                    href={parsed.href}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="text-sm text-white hover:text-[#ccc] break-words min-w-0 transition-colors"
                  >
                    {parsed.display}
                  </a>
                ) : (
                  <span className="text-sm text-white break-words min-w-0">{parsed.display}</span>
                )}
              </div>
            )}
            {endpoint && (
              <div className="flex items-center justify-between">
                <span className="text-xs text-[#aaa]">Endpoint</span>
                <span className="text-xs text-white font-mono truncate max-w-[75%] text-right">{endpoint}</span>
              </div>
            )}
            {method && (
              <div className="flex items-center justify-between">
                <span className="text-xs text-[#aaa]">Method</span>
                <span className="text-xs text-white font-mono">{method}</span>
              </div>
            )}
            {hasLocations && (
              <div>
                <span className="text-xs text-[#aaa] mb-1.5 block">Locations</span>
                <div className="space-y-0.5">
                  {fixLocations!.map((loc, i) => {
                    const label = `${loc.file}:${loc.start_line}`;
                    const href = location_meta
                      ? buildLocationHref(location_meta.repo_url, location_meta.provider, location_meta.branch, loc.file, loc.start_line)
                      : null;
                    return href ? (
                      <a
                        key={`loc-${i}`}
                        href={href}
                        target="_blank"
                        rel="noopener noreferrer"
                        className="text-[13px] text-[#888] hover:text-white font-mono break-all transition-colors block"
                      >
                        {label}
                      </a>
                    ) : (
                      <span key={`loc-${i}`} className="text-[13px] text-[#888] font-mono break-all block">
                        {label}
                      </span>
                    );
                  })}
                </div>
              </div>
            )}
          </div>
        </div>
      )}

      {/* ─── Risk Assessment (human-friendly CVSS) ─── */}
      {hasBreakdown && (
        <div className="border-t border-[#191919] pt-4">
          <button
            onClick={() => setRiskOpen(!riskOpen)}
            className="flex items-center justify-between w-full mb-2.5 group"
            aria-expanded={riskOpen}
          >
            <span className="text-xs font-medium text-[#aaa]">Risk Assessment</span>
            <ChevronDown className={`w-3.5 h-3.5 text-[#555] group-hover:text-white transition-transform ${riskOpen ? "" : "-rotate-90"}`} aria-hidden="true" />
          </button>
          <div className={`space-y-3 ${riskOpen ? "" : "hidden"}`}>
            {FACTOR_GROUPS.map((group) => {
              const factors = group.keys.filter(
                (k) => (cvss_breakdown as unknown as Record<string, string | null>)[k] != null
              );
              if (factors.length === 0) return null;
              return (
                <div key={group.label}>
                  <div className="flex items-center justify-between mb-1.5">
                    <p className="text-[10px] uppercase tracking-wider text-[#444] font-medium">
                      {group.label}
                    </p>
                    <p className="text-[10px] uppercase tracking-wider text-[#444] font-medium mr-2">
                      Risk
                    </p>
                  </div>
                  <div className="space-y-1">
                    {factors.map((key) => {
                      const raw = (cvss_breakdown as unknown as Record<string, string | null>)[key];
                      const level = raw ? (RISK_LEVEL[key]?.[raw] ?? "low") : "low";
                      const label = raw ? (HUMAN_LABELS[key]?.[raw] ?? raw) : "N/A";
                      return (
                        <div key={key} className="flex items-center justify-between py-0.5">
                          <span className="text-[12px] text-[#aaa]">{label}</span>
                          <span className={`text-[10px] font-medium px-1.5 py-0.5 rounded border ${RISK_BADGE[level]}`}>
                            {level}
                          </span>
                        </div>
                      );
                    })}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </aside>
  );
}
