/**
 * AgentGhostView.tsx — GAP-4: Mobile Agent Ghost View
 *
 * Overlay slide-up dal bottom (≤ 30vh) che appare automaticamente
 * quando l'agente scrive file nel VFS, mostrando quale file sta modificando
 * e le prime 8 righe del contenuto + progress bar 4s → chiusura automatica.
 *
 * Si sopprime automaticamente se il file modificato è quello aperto nell'editor.
 * Rispetta safe-area-inset-bottom e prefers-reduced-motion.
 *
 * @module AgentGhostView
 */

import { useState, useEffect, useRef, useCallback, memo } from "react";
import type * as React from "react";
import { X, FileText, Eye } from "lucide-react";
import { eventRuntime }  from "@/core/events";
import { vfsAsync }      from "@/lib/vfsDb";
import { Z_INDEX }       from "@/lib/zindex";

// ── Costanti ──────────────────────────────────────────────────────────────────

const AUTO_CLOSE_MS  = 4_000;
const MAX_DIFF_LINES = 8;
const MAX_READ_CHARS = 8_000;
const MAX_LINE_WIDTH = 72;

// ── Types ─────────────────────────────────────────────────────────────────────

interface GhostEntry {
  path:    string;
  snippet: string;
  at:      number;
}

// ── Helpers ───────────────────────────────────────────────────────────────────

function _basename(path: string): string { return path.split("/").pop() || path; }

function _extColor(path: string): string {
  const ext = path.split(".").pop()?.toLowerCase() ?? "";
  const map: Record<string, string> = {
    ts: "#3178c6", tsx: "#3178c6", js: "#f7df1e", jsx: "#61dafb",
    py: "#3572a5", go: "#00add8", rs: "#dea584", json: "#ffa500",
    md: "#83a598", css: "#563d7c", html: "#e34c26", sh: "#89d051",
  };
  return map[ext] ?? "#888";
}

function _truncateLines(content: string, maxLines: number, maxWidth: number): string {
  return content.split("\n").slice(0, maxLines)
    .map(l => l.length > maxWidth ? l.slice(0, maxWidth) + "…" : l)
    .join("\n");
}

// ── Componente ────────────────────────────────────────────────────────────────

interface AgentGhostViewProps {
  enabled?:       boolean;
  activeFilePath?: string | null;
}

const AgentGhostView = memo(function AgentGhostView({
  enabled = true,
  activeFilePath = null,
}: AgentGhostViewProps) {
  const [visible,    setVisible]    = useState(false);
  const [entry,      setEntry]      = useState<GhostEntry | null>(null);
  const [batchCount, setBatchCount] = useState(0);

  const autoCloseTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const mountedRef     = useRef(true);

  useEffect(() => {
    mountedRef.current = true;
    return () => {
      mountedRef.current = false;
      if (autoCloseTimer.current) clearTimeout(autoCloseTimer.current);
    };
  }, []);

  const resetAutoClose = useCallback(() => {
    if (autoCloseTimer.current) clearTimeout(autoCloseTimer.current);
    autoCloseTimer.current = setTimeout(() => {
      if (mountedRef.current) { setVisible(false); setBatchCount(0); }
    }, AUTO_CLOSE_MS);
  }, []);

  const handleClose = useCallback(() => {
    if (autoCloseTimer.current) clearTimeout(autoCloseTimer.current);
    setVisible(false);
    setBatchCount(0);
  }, []);

  useEffect(() => {
    if (!enabled) return;
    const unsub = eventRuntime.on("file_patch", async (evt) => {
      if (evt.path === "@vfs/sync_commit") return;
      if (evt.path === activeFilePath)     return;
      if (!mountedRef.current) return;

      let snippet = "";
      try {
        const content = await vfsAsync.read(evt.path);
        if (content) snippet = _truncateLines(content.slice(0, MAX_READ_CHARS), MAX_DIFF_LINES, MAX_LINE_WIDTH);
      } catch { snippet = "(anteprima non disponibile)"; }

      if (!mountedRef.current) return;
      setEntry({ path: evt.path, snippet, at: Date.now() });
      setBatchCount(c => c + 1);
      setVisible(true);
      resetAutoClose();
    });
    return unsub;
  }, [enabled, activeFilePath, resetAutoClose]);

  if (!visible || !entry) return null;

  const filename = _basename(entry.path);
  const extColor = _extColor(entry.path);

  return (
    <div
      role="status"
      aria-live="polite"
      aria-label={`Agente sta modificando ${filename}`}
      style={{
        position: "fixed", left: 0, right: 0, bottom: 0,
        zIndex: Z_INDEX.MODAL - 1,
        animation: "ghostSlideUp 250ms ease-out",
        paddingBottom: "env(safe-area-inset-bottom, 0px)",
      }}
    >
      <div style={{
        position: "absolute", inset: 0,
        background: "rgba(6,6,18,0.80)",
        backdropFilter: "blur(12px)",
        WebkitBackdropFilter: "blur(12px)",
        pointerEvents: "none",
      }} />
      <div style={{
        position: "relative", margin: "0 0", padding: "12px 16px 14px",
        borderTop: "1px solid rgba(99,102,241,0.30)",
        maxHeight: "30vh", overflow: "hidden",
        display: "flex", flexDirection: "column", gap: 8,
      }}>
        {/* Header */}
        <div style={{ display: "flex", alignItems: "center", gap: 8, flexShrink: 0 }}>
          <Eye size={14} color="#818cf8" />
          <span style={{ fontSize: "0.72rem", color: "#818cf8", fontWeight: 700, letterSpacing: "0.05em" }}>
            AGENTE STA MODIFICANDO
          </span>
          {batchCount > 1 && (
            <span style={{
              fontSize: "0.65rem", fontWeight: 700,
              background: "rgba(99,102,241,0.20)", color: "#818cf8",
              padding: "1px 7px", borderRadius: 10,
              border: "1px solid rgba(99,102,241,0.30)",
            }}>
              {batchCount} file
            </span>
          )}
          <div style={{ flex: 1 }} />
          <button
            onClick={handleClose}
            aria-label="Chiudi Ghost View"
            style={{ all: "unset", cursor: "pointer", padding: 6, color: "#4a4a78", touchAction: "manipulation" }}
          >
            <X size={16} />
          </button>
        </div>

        {/* File path */}
        <div style={{ display: "flex", alignItems: "center", gap: 6, flexShrink: 0 }}>
          <FileText size={13} color={extColor} />
          <span style={{
            fontSize: "0.78rem", fontWeight: 600, color: "#d0d0f0",
            fontFamily: "monospace", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
          }}>
            {entry.path}
          </span>
        </div>

        {/* Snippet */}
        {entry.snippet && (
          <pre style={{
            margin: 0, padding: "8px 10px",
            background: "rgba(255,255,255,0.03)",
            border: "1px solid rgba(99,102,241,0.12)",
            borderLeft: `3px solid ${extColor}`,
            borderRadius: 6, fontSize: "0.68rem", color: "#a0a0c0",
            fontFamily: "monospace", lineHeight: 1.5,
            overflow: "hidden", whiteSpace: "pre", flex: 1, minHeight: 0,
          }}>
            {entry.snippet}
          </pre>
        )}

        {/* Progress bar */}
        <div style={{ position: "absolute", bottom: 0, left: 0, right: 0, height: 2, background: "rgba(99,102,241,0.15)" }}>
          <div style={{
            height: "100%", background: "#6366f1",
            animation: `ghostProgress ${AUTO_CLOSE_MS}ms linear forwards`,
            transformOrigin: "left center",
          }} />
        </div>
      </div>

      <style>{`
        @keyframes ghostSlideUp {
          from { transform: translateY(100%); opacity: 0; }
          to   { transform: translateY(0);    opacity: 1; }
        }
        @keyframes ghostProgress {
          from { transform: scaleX(1); }
          to   { transform: scaleX(0); }
        }
        @media (prefers-reduced-motion: reduce) {
          @keyframes ghostSlideUp  { from { opacity: 0; } to { opacity: 1; } }
          @keyframes ghostProgress { from { opacity: 1; } to { opacity: 0; } }
        }
      `}</style>
    </div>
  );
});

export default AgentGhostView;
