/**
 * RecentFileTabs.tsx — S613: tab strip file recenti sopra il code editor
 *
 * Mostra gli ultimi MAX_RECENT file aperti come tab cliccabili (pattern VS Code).
 * Integrato nella riga sopra FileEditor nel top Panel del PanelGroup S612.
 *
 * - Click tab → apre il file (setOpenFile + setRequestOpenPath)
 * - × → chiude il tab (closeRecentFile; se era il file attivo, apre il precedente)
 * - Tab attivo evidenziato in blu
 * - Overflow orizzontale (no wrap) con scroll invisibile
 *
 * S614: import type { CSSProperties, RefObject } — import diretto da "react", non prefissato
 *       data-path su FileTab per useActiveTabScroll
 *       auto-scroll del tab attivo nella viewport
 *
 * S616: badge arancione "●" sui tab modificati dall'agente mentre erano in background.
 *       onVfsChanged → markDirty(path) per file in recentFiles che non sono aperti.
 *       Apertura tab → clearDirty(path) automatica via setOpenFile.
 */

import { useRef, useEffect, memo } from "react";
import type { CSSProperties, RefObject } from "react";
import { X } from "lucide-react";
import { useWorkspaceStore } from "@/store/workspaceStore";
import { onVfsFileChanged } from "@/lib/vfsDb";  // S619: usa onVfsFileChanged per dirty badge preciso
import type { VFSFile } from "@/lib/vfsDb";

// ─── Icon helpers ─────────────────────────────────────────────────────────────

function fileIcon(name: string): string {
  if (name.endsWith(".py"))     return "🐍";
  if (name.endsWith(".ts") || name.endsWith(".tsx")) return "📘";
  if (name.endsWith(".js") || name.endsWith(".jsx")) return "📜";
  if (name.endsWith(".json"))   return "📋";
  if (name.endsWith(".html"))   return "🌐";
  if (name.endsWith(".css") || name.endsWith(".scss")) return "🎨";
  if (name.endsWith(".md"))     return "📝";
  if (name.endsWith(".sh"))     return "⚙️";
  return "📄";
}

// ─── Single tab ───────────────────────────────────────────────────────────────

function FileTab({
  file,
  isActive,
  isDirty,
  onOpen,
  onClose,
}: {
  file: VFSFile;
  isActive: boolean;
  isDirty: boolean;
  onOpen: (f: VFSFile) => void;
  onClose: (path: string) => void;
}) {
  return (
    <div
      role="tab"
      aria-selected={isActive}
      data-path={file.path}
      onClick={() => onOpen(file)}
      title={isDirty ? `${file.path} — modificato dall'agente` : file.path}
      style={{
        display: "flex", alignItems: "center", gap: 4,
        padding: "0 10px 0 8px",
        height: "100%",
        flexShrink: 0,
        cursor: "pointer",
        background: isActive ? "rgba(99,102,241,0.12)" : "transparent",
        borderRight: "1px solid rgba(99,102,241,0.08)",
        borderBottom: isActive ? "2px solid #818cf8" : "2px solid transparent",
        color: isActive ? "#c7d2fe" : "#4a4a78",
        fontSize: "0.68rem",
        transition: "color 0.15s, background 0.15s, border-color 0.15s",
        userSelect: "none",
        maxWidth: 160,
        minWidth: 60,
        position: "relative",
      }}
      onMouseEnter={e => {
        if (!isActive) {
          e.currentTarget.style.color = "#818cf8";
          e.currentTarget.style.background = "rgba(99,102,241,0.06)";
        }
      }}
      onMouseLeave={e => {
        if (!isActive) {
          e.currentTarget.style.color = "#4a4a78";
          e.currentTarget.style.background = "transparent";
        }
      }}
    >
      {/* S616: dirty dot — arancione, pulsa quando il file è stato modificato */}
      {isDirty && !isActive && (
        <span
          aria-label="File modificato dall'agente"
          style={{
            display: "inline-block",
            width: 6, height: 6,
            borderRadius: "50%",
            background: "#f97316",
            flexShrink: 0,
            animation: "mem-tab-pulse 1.5s ease-in-out infinite",
          }}
        />
      )}

      <span style={{ fontSize: "0.72rem", flexShrink: 0 }}>{fileIcon(file.name)}</span>
      <span style={{
        overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
        flex: 1, minWidth: 0,
        color: isDirty && !isActive ? "#fb923c" : undefined,
      }}>
        {file.name}
      </span>
      <button
        onClick={e => { e.stopPropagation(); onClose(file.path); }}
        aria-label={`Chiudi ${file.name}`}
        style={{
          display: "flex", alignItems: "center", justifyContent: "center",
          width: 14, height: 14, flexShrink: 0,
          background: "none", border: "none", cursor: "pointer",
          color: "inherit", borderRadius: 4, padding: 0,
          opacity: 0.6,
          transition: "opacity 0.15s, background 0.15s",
        }}
        onMouseEnter={e => { e.currentTarget.style.opacity = "1"; e.currentTarget.style.background = "rgba(239,68,68,0.20)"; }}
        onMouseLeave={e => { e.currentTarget.style.opacity = "0.6"; e.currentTarget.style.background = "none"; }}
      >
        <X size={10} strokeWidth={2.5} />
      </button>
    </div>
  );
}

// ─── Tab strip ────────────────────────────────────────────────────────────────

// ─── Active tab auto-scroll ────────────────────────────────────────────────── S614

function useActiveTabScroll(
  containerRef: RefObject<HTMLDivElement | null>,
  activePath: string | null,
) {
  useEffect(() => {
    if (!containerRef.current || !activePath) return;
    const el = containerRef.current.querySelector(
      `[data-path="${CSS.escape(activePath)}"]`,
    ) as HTMLElement | null;
    el?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" });
  }, [activePath, containerRef]);
}

export const RecentFileTabs = memo(function RecentFileTabs() {
  const recentFiles        = useWorkspaceStore(s => s.recentFiles);
  const openFile           = useWorkspaceStore(s => s.openFile);
  const dirtyPaths         = useWorkspaceStore(s => s.dirtyPaths);       // S616
  const setOpenFile        = useWorkspaceStore(s => s.setOpenFile);
  const setRequestOpenPath = useWorkspaceStore(s => s.setRequestOpenPath);
  const closeRecentFile    = useWorkspaceStore(s => s.closeRecentFile);
  const containerRef       = useRef<HTMLDivElement | null>(null);

  // S614: scroll il tab attivo nella viewport quando cambia
  useActiveTabScroll(containerRef, openFile?.path ?? null);

  // S619: usa onVfsFileChanged per dirty badge preciso — segna solo il file effettivamente modificato
  // (fix S616: era onVfsChanged che marcava TUTTI i tab non-attivi ad ogni write)
  useEffect(() => {
    return onVfsFileChanged((changedPath) => {
      const { recentFiles: rf, openFile: of, markDirty: md } =
        useWorkspaceStore.getState();
      // Marca dirty solo se il file è nei tab recenti E non è quello attivo
      const isRecent = rf.some(f => f.path === changedPath);
      if (isRecent && of?.path !== changedPath) {
        md(changedPath);
      }
    });
  }, []);

  // Non renderizzare se non ci sono file recenti
  if (recentFiles.length === 0) return null;

  const handleOpen = (file: VFSFile) => {
    setOpenFile(file);             // S616: clearDirty avviene dentro setOpenFile
    setRequestOpenPath(file.path);
  };

  const handleClose = (path: string) => {
    closeRecentFile(path);         // S616: clearDirty avviene dentro closeRecentFile
  };

  return (
    <div
      ref={containerRef}
      role="tablist"
      aria-label="File recenti"
      style={{
        display: "flex",
        alignItems: "stretch",
        height: 32,
        background: "rgba(4,5,16,0.98)",
        borderBottom: "1px solid rgba(99,102,241,0.12)",
        overflowX: "auto",
        overflowY: "hidden",
        flexShrink: 0,
        // Nascondi scrollbar ma permetti scroll
        scrollbarWidth: "none",
        msOverflowStyle: "none",
      } as CSSProperties}
    >
      {recentFiles.map(file => (
        <FileTab
          key={file.path}
          file={file}
          isActive={openFile?.path === file.path}
          isDirty={dirtyPaths.has(file.path)}
          onOpen={handleOpen}
          onClose={handleClose}
        />
      ))}
    </div>
  );
});
