const { useState, useEffect, useRef, useCallback } = React;
const sb = window.sbClient;

// ─── Costanti ───
const CATEGORIE = [
  "apertura",
  "tono",
  "gestione obiezione",
  "qualificazione",
  "chiusura",
  "info inventata",
  "altro",
];

const OUTCOME_LABEL = {
  qualificato: "Qualificato ✅",
  da_risentire: "Da risentire 🔁",
  non_interessato: "Non interessato ✖",
  non_in_target: "Non in target ✖",
  escalation: "Escalation ⚠",
  nr: "Nessuna risposta",
  segreteria: "Segreteria",
};

// ─── Helpers ───
function mmss(sec) {
  sec = Math.max(0, Math.floor(sec || 0));
  const m = Math.floor(sec / 60);
  const s = sec % 60;
  return `${m}:${String(s).padStart(2, "0")}`;
}

function fmtDate(iso) {
  if (!iso) return "";
  const d = new Date(iso);
  return d.toLocaleString("it-IT", {
    day: "2-digit", month: "2-digit", year: "numeric",
    hour: "2-digit", minute: "2-digit",
  });
}

async function getToken() {
  const { data } = await sb.auth.getSession();
  return data?.session?.access_token || null;
}

async function getEmail() {
  const { data } = await sb.auth.getSession();
  return data?.session?.user?.email || null;
}

// ─── Stelle ───
function StarRating({ rating, onRate, size = 22 }) {
  const [hover, setHover] = useState(null);
  const display = hover !== null ? hover : (rating || 0);
  return (
    <div style={{ display: "flex", gap: 3 }}>
      {[1, 2, 3, 4, 5].map((n) => (
        <span
          key={n}
          onMouseEnter={() => setHover(n)}
          onMouseLeave={() => setHover(null)}
          onClick={() => onRate(n)}
          style={{
            fontSize: size, cursor: "pointer", lineHeight: 1,
            color: n <= display ? "#f4c089" : "rgba(255,255,255,0.18)",
            transition: "color 0.1s",
          }}
        >★</span>
      ))}
    </div>
  );
}

// ─── Card lista ───
function CallCard({ call, onOpen }) {
  return (
    <div className="card" onClick={() => onOpen(call)}>
      <div className="card-top">
        <span className="lead-name">{call.lead_name || "Senza nome"}</span>
        {call.stars ? <span className="stars-badge">{"★".repeat(call.stars)}</span> : null}
      </div>
      <div className="card-meta">
        <span className="badge">{OUTCOME_LABEL[call.outcome] || call.outcome || "—"}</span>
        {call.duration_sec ? <span className="dim">· {mmss(call.duration_sec)}</span> : null}
      </div>
      <div className="card-bottom">
        <span className="dim">{fmtDate(call.created_at)}</span>
        {call.comment_count ? <span className="comment-pill">💬 {call.comment_count}</span> : null}
        {!call.recording_key ? <span className="no-audio">no audio</span> : null}
      </div>
    </div>
  );
}

// ─── Dettaglio call ───
function CallDetail({ call, token, email, onBack, onChanged }) {
  const audioRef = useRef(null);
  const [comments, setComments] = useState([]);
  const [feedback, setFeedback] = useState(null);
  const [draftCat, setDraftCat] = useState(CATEGORIE[0]);
  const [draftText, setDraftText] = useState("");
  const [draftSec, setDraftSec] = useState(null);
  const [notaGen, setNotaGen] = useState("");
  const [savingNota, setSavingNota] = useState(false);

  const audioSrc = call.recording_key && token
    ? `${window.REC_AUDIO_BASE}/audio?key=${encodeURIComponent(call.recording_key)}&token=${encodeURIComponent(token)}`
    : null;

  const loadComments = useCallback(async () => {
    const { data } = await sb
      .from("voice_call_comments")
      .select("*")
      .eq("call_id", call.id)
      .order("timestamp_sec", { ascending: true });
    setComments(data || []);
  }, [call.id]);

  const loadFeedback = useCallback(async () => {
    const { data } = await sb
      .from("voice_call_feedback")
      .select("*")
      .eq("call_id", call.id)
      .maybeSingle();
    setFeedback(data || null);
    setNotaGen(data?.nota_generale || "");
  }, [call.id]);

  useEffect(() => { loadComments(); loadFeedback(); }, [loadComments, loadFeedback]);

  // Segna il punto corrente del player per il commento.
  const markHere = () => {
    const sec = audioRef.current ? Math.floor(audioRef.current.currentTime) : 0;
    setDraftSec(sec);
  };

  const seekTo = (sec) => {
    if (audioRef.current) {
      audioRef.current.currentTime = sec;
      audioRef.current.play().catch(() => {});
    }
  };

  const addComment = async () => {
    if (!draftText.trim()) return;
    const sec = draftSec != null
      ? draftSec
      : (audioRef.current ? Math.floor(audioRef.current.currentTime) : 0);
    await sb.from("voice_call_comments").insert({
      call_id: call.id,
      timestamp_sec: sec,
      reason: draftCat,
      comment: draftText.trim(),
      created_by: email,
    });
    setDraftText("");
    setDraftSec(null);
    loadComments();
    onChanged && onChanged();
  };

  const deleteComment = async (id) => {
    await sb.from("voice_call_comments").delete().eq("id", id);
    loadComments();
    onChanged && onChanged();
  };

  const setStars = async (n) => {
    await sb.from("voice_call_feedback").upsert(
      {
        call_id: call.id,
        stars: n,
        nota_generale: notaGen || null,
        reviewed_by: email,
        reviewed_at: new Date().toISOString(),
      },
      { onConflict: "call_id" }
    );
    loadFeedback();
    onChanged && onChanged();
  };

  const saveNota = async () => {
    setSavingNota(true);
    await sb.from("voice_call_feedback").upsert(
      {
        call_id: call.id,
        stars: feedback?.stars || null,
        nota_generale: notaGen || null,
        reviewed_by: email,
        reviewed_at: new Date().toISOString(),
      },
      { onConflict: "call_id" }
    );
    setSavingNota(false);
    loadFeedback();
  };

  return (
    <div className="detail">
      <button className="back" onClick={onBack}>← Tutte le call</button>

      <div className="detail-head">
        <h2>{call.lead_name || "Senza nome"}</h2>
        <span className="badge">{OUTCOME_LABEL[call.outcome] || call.outcome}</span>
        <span className="dim">{fmtDate(call.created_at)}</span>
      </div>

      {/* Player */}
      {audioSrc ? (
        <div className="player-box">
          <audio ref={audioRef} src={audioSrc} controls preload="metadata" style={{ width: "100%" }} />
          <button className="mark-btn" onClick={markHere}>💬 Commenta a questo punto</button>
        </div>
      ) : (
        <div className="player-box dim">Nessuna registrazione disponibile per questa call.</div>
      )}

      {/* Form commento */}
      <div className="comment-form">
        <div className="comment-form-row">
          <span className="ts-chip">
            {draftSec != null ? mmss(draftSec) : "punto corrente"}
          </span>
          <select value={draftCat} onChange={(e) => setDraftCat(e.target.value)}>
            {CATEGORIE.map((c) => <option key={c} value={c}>{c}</option>)}
          </select>
        </div>
        <textarea
          placeholder="Qui è sbagliato perché…"
          value={draftText}
          onChange={(e) => setDraftText(e.target.value)}
          rows={2}
        />
        <button className="primary" onClick={addComment} disabled={!draftText.trim()}>
          Aggiungi commento
        </button>
      </div>

      {/* Lista commenti */}
      <div className="comments">
        <h3>Commenti ({comments.length})</h3>
        {comments.length === 0 && <div className="dim">Nessun commento ancora.</div>}
        {comments.map((c) => (
          <div className="comment" key={c.id}>
            <button className="ts-link" onClick={() => seekTo(c.timestamp_sec)}>{mmss(c.timestamp_sec)}</button>
            <div className="comment-body">
              <span className="cat">{c.reason}</span>
              <span className="ctext">{c.comment}</span>
            </div>
            <button className="del" onClick={() => deleteComment(c.id)}>×</button>
          </div>
        ))}
      </div>

      {/* Voto generale */}
      <div className="feedback-box">
        <h3>Voto generale</h3>
        <StarRating rating={feedback?.stars} onRate={setStars} />
        <textarea
          placeholder="Nota generale sulla call (cosa ha funzionato / cosa no)…"
          value={notaGen}
          onChange={(e) => setNotaGen(e.target.value)}
          rows={3}
          style={{ marginTop: 10 }}
        />
        <button className="primary" onClick={saveNota} disabled={savingNota}>
          {savingNota ? "Salvataggio…" : "Salva nota generale"}
        </button>
      </div>

      {/* Nota generata dal bot + transcript */}
      <div className="info-grid">
        <div className="info-col">
          <h3>Nota generata (bot)</h3>
          <pre className="pre">{call.nota_generata || "—"}</pre>
        </div>
        <div className="info-col">
          <h3>Transcript</h3>
          <pre className="pre">{call.transcript || "—"}</pre>
        </div>
      </div>
    </div>
  );
}

// ─── App ───
function App() {
  const [calls, setCalls] = useState([]);
  const [loading, setLoading] = useState(true);
  const [selected, setSelected] = useState(null);
  const [token, setToken] = useState(null);
  const [email, setEmail] = useState(null);

  const load = useCallback(async () => {
    setLoading(true);
    const { data: callRows } = await sb
      .from("voice_calls")
      .select("*")
      .order("created_at", { ascending: false });
    const list = callRows || [];

    // feedback (stelle) + conteggio commenti
    const ids = list.map((c) => c.id);
    let fbMap = {}, cntMap = {};
    if (ids.length) {
      const { data: fbs } = await sb
        .from("voice_call_feedback")
        .select("call_id, stars")
        .in("call_id", ids);
      (fbs || []).forEach((f) => { fbMap[f.call_id] = f.stars; });
      const { data: cmts } = await sb
        .from("voice_call_comments")
        .select("call_id")
        .in("call_id", ids);
      (cmts || []).forEach((c) => { cntMap[c.call_id] = (cntMap[c.call_id] || 0) + 1; });
    }
    setCalls(list.map((c) => ({ ...c, stars: fbMap[c.id], comment_count: cntMap[c.id] || 0 })));
    setLoading(false);
  }, []);

  useEffect(() => {
    (async () => {
      setToken(await getToken());
      setEmail(await getEmail());
      load();
    })();
  }, [load]);

  const logout = async () => {
    await sb.auth.signOut();
    window.location.replace("/login.html");
  };

  if (selected) {
    return (
      <div className="wrap">
        <CallDetail
          call={selected}
          token={token}
          email={email}
          onBack={() => { setSelected(null); load(); }}
          onChanged={load}
        />
      </div>
    );
  }

  return (
    <div className="wrap">
      <header className="topbar">
        <div className="brand">Review Call AI<span style={{ color: "#f4c089" }}>.</span></div>
        <button className="logout" onClick={logout}>Esci</button>
      </header>
      {loading ? (
        <div className="dim center">Caricamento…</div>
      ) : calls.length === 0 ? (
        <div className="dim center">Nessuna chiamata registrata ancora.</div>
      ) : (
        <div className="grid">
          {calls.map((c) => <CallCard key={c.id} call={c} onOpen={setSelected} />)}
        </div>
      )}
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
