/* global React, IconStar, IconPlus, IconMore, IconChevR, IconCalendar */
// Kanban pipeline — una tarjeta por llamada de Calendly. Drag & drop,
// etapas editables, scroll horizontal. Compartido por todos los pipelines.

const { useState, useRef, useEffect } = React;

const STAGE_COLOR_SWATCHES = [
  "#8b5cf6", "#3b82f6", "#0e9f6e", "#f59e0b", "#059669",
  "#ef4444", "#14b8a6", "#ec4899", "#6366f1", "#94a3b8"];

// ---- Etiqueta de fecha/hora corta para la tarjeta ----------------
function shortWhen(date) {
  if (!(date instanceof Date)) return "";
  const now = new Date();
  const sameDay = (a, b) => a.toDateString() === b.toDateString();
  const tom = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
  const hh = date.toLocaleTimeString("es-ES", { hour: "2-digit", minute: "2-digit", hour12: false });
  if (sameDay(date, now)) return "Hoy " + hh;
  if (sameDay(date, tom)) return "Mañana " + hh;
  if (date < now) return date.toLocaleDateString("es-ES", { day: "numeric", month: "short" });
  return date.toLocaleDateString("es-ES", { weekday: "short", day: "numeric" }) + " " + hh;
}

function StageDot({ color, onClick, editable }) {
  return (
    <span className="stage-dot" style={{ background: color, cursor: editable ? "pointer" : "default" }}
          onClick={editable ? onClick : undefined} title={editable ? "Cambiar color" : undefined}/>);
}

function SourceBadge({ source, size = "sm" }) {
  const SOURCES = window.REVOLVR_DATA.SOURCES;
  const s = SOURCES[source] || { label: source, color: "#94a3b8" };
  return (
    <span className="source-badge" data-size={size} style={{ "--src": s.color }}>
      <span className="dot"/>{s.label}
    </span>);
}

function KanCard({ c, onOpen, onDragStart, onDragEnd, isDragging, showCloser, justLanded }) {
  const { CLOSERS, CALL_STATUS } = window.REVOLVR_DATA;
  const closer = CLOSERS.find((x) => x.id === c.closerId);
  const st = CALL_STATUS[c.status] || {};
  return (
    <div className={"kan-card" + (isDragging ? " dragging" : "") + (justLanded ? " just-landed" : "")}
         draggable onDragStart={(e) => onDragStart(e, c.id)} onDragEnd={onDragEnd}
         onClick={() => onOpen(c.id)}>
      <div className="top-row">
        <div className="rv-avatar sm" style={{ background: closer ? closer.color : "var(--accent)" }}>
          {c.name.split(" ").map((s) => s[0]).slice(0, 2).join("")}
        </div>
        <div className="name">{c.name}</div>
        <span className="status-dot" style={{ background: st.color }} title={st.label}/>
      </div>
      <div className="evt">{c.eventType}</div>
      <div className="msg">{c.form.objetivo}</div>
      {c.stage === "ganada" && c.sale && <SaleBadge sale={c.sale}/>}
      <div className="meta-row">
        <SourceBadge source={c.utm.source}/>
        {showCloser && closer && <span className="closer-chip">{closer.name.split(" ")[0]}</span>}
        <span className="time"><IconCalendar size={10}/> {shortWhen(c.scheduledAt)}</span>
      </div>
    </div>);
}

function paymentState(sale) {
  const pagado = sale.tipo === "total" ? sale.total : (sale.pagado || 0);
  const saldo = Math.max(0, sale.total - pagado);
  return { pagado, saldo, paid: saldo <= 0 };
}

function SaleBadge({ sale }) {
  const { saldo, paid } = paymentState(sale);
  return (
    <div className="sale-badge" data-paid={paid ? "true" : undefined}>
      <span className="sb-prog">{sale.programa}</span>
      <span className="sb-amt">{"$" + (sale.total || 0).toLocaleString("en-US")}</span>
      <span className="sb-pay">{paid ? "pagado" : "saldo $" + saldo.toLocaleString("en-US")}</span>
    </div>);
}

function KanColumn({
  stage, calls, onOpen, onDrop, dragId, setDragId, showCloser, justMovedId,
  hoverStage, setHoverStage, onRename, onRecolor, onDelete, onMove, isFirst, isLast,
  stageDragId, setStageDragId, stageHoverId, setStageHoverId, onReorderStages
}) {
  const isOver = hoverStage === stage.id && dragId;
  const [menuOpen, setMenuOpen] = useState(false);
  const [colorPickerOpen, setColorPickerOpen] = useState(false);
  const [editingName, setEditingName] = useState(false);
  const [draftName, setDraftName] = useState(stage.label);
  const [overIndex, setOverIndex] = useState(null);
  const menuRef = useRef(null);
  const inputRef = useRef(null);

  useEffect(() => {
    if (!menuOpen && !colorPickerOpen) return;
    const onDown = (e) => {
      if (menuRef.current && !menuRef.current.contains(e.target)) { setMenuOpen(false); setColorPickerOpen(false); }
    };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [menuOpen, colorPickerOpen]);

  useEffect(() => {
    if (editingName && inputRef.current) { inputRef.current.focus(); inputRef.current.select(); }
  }, [editingName]);

  const commitName = () => {
    const n = draftName.trim();
    if (n && n !== stage.label) onRename(stage.id, n);
    setEditingName(false);
  };

  return (
    <div className={"kan-col" + (stageDragId === stage.id ? " stage-dragging" : "")}>
      <div
        className={"kan-col-head" + (stageHoverId === stage.id && stageDragId && stageDragId !== stage.id ? " stage-drop-target" : "")}
        draggable={!editingName}
        onDragStart={(e) => { if (editingName) return; setStageDragId(stage.id); e.dataTransfer.effectAllowed = "move"; }}
        onDragEnd={() => { setStageDragId(null); setStageHoverId(null); }}
        onDragOver={(e) => { if (stageDragId && stageDragId !== stage.id) { e.preventDefault(); e.stopPropagation(); setStageHoverId(stage.id); } }}
        onDragLeave={(e) => { if (stageDragId && e.currentTarget === e.target) setStageHoverId(null); }}
        onDrop={(e) => { if (stageDragId && stageDragId !== stage.id) { e.preventDefault(); e.stopPropagation(); onReorderStages(stageDragId, stage.id); setStageDragId(null); setStageHoverId(null); } }}>
        <span className="col-grip" title="Arrastra para reordenar" aria-hidden="true">
          <svg width="8" height="12" viewBox="0 0 8 12" fill="currentColor"><circle cx="2" cy="2" r="1"/><circle cx="6" cy="2" r="1"/><circle cx="2" cy="6" r="1"/><circle cx="6" cy="6" r="1"/><circle cx="2" cy="10" r="1"/><circle cx="6" cy="10" r="1"/></svg>
        </span>
        <StageDot color={stage.color} editable onClick={() => { setColorPickerOpen((v) => !v); setMenuOpen(false); }}/>
        {editingName ?
          <input ref={inputRef} className="title-input" value={draftName}
                 onChange={(e) => setDraftName(e.target.value)} onBlur={commitName}
                 onKeyDown={(e) => { if (e.key === "Enter") commitName(); if (e.key === "Escape") { setDraftName(stage.label); setEditingName(false); } }}/> :
          <span className="title-text" onDoubleClick={() => setEditingName(true)} title="Doble clic para renombrar">{stage.label}</span>}
        <span className="count">{calls.length}</span>
        <button className="col-kebab" onClick={() => { setMenuOpen((v) => !v); setColorPickerOpen(false); }} title="Opciones"><IconMore size={13}/></button>

        {(menuOpen || colorPickerOpen) &&
          <div className="col-menu" ref={menuRef}>
            {colorPickerOpen ?
              <>
                <div style={{ padding: "8px 10px 4px", fontSize: 11, color: "var(--text-3)", fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em" }}>Color de etapa</div>
                <div className="swatch-row">
                  {STAGE_COLOR_SWATCHES.map((cc) =>
                    <span key={cc} className="sw" data-active={cc === stage.color ? "true" : undefined} style={{ background: cc }} onClick={() => { onRecolor(stage.id, cc); setColorPickerOpen(false); }}/>)}
                </div>
              </> :
              <>
                <button onClick={() => { setEditingName(true); setMenuOpen(false); }}>Renombrar etapa</button>
                <button onClick={() => { setColorPickerOpen(true); setMenuOpen(false); }}>Cambiar color</button>
                <hr/>
                <button onClick={() => { onMove(stage.id, -1); setMenuOpen(false); }} disabled={isFirst} style={isFirst ? { opacity: 0.4, cursor: "not-allowed" } : undefined}>← Mover a la izquierda</button>
                <button onClick={() => { onMove(stage.id, +1); setMenuOpen(false); }} disabled={isLast} style={isLast ? { opacity: 0.4, cursor: "not-allowed" } : undefined}>Mover a la derecha →</button>
                <hr/>
                <button className="danger" onClick={() => { onDelete(stage.id); setMenuOpen(false); }}>Eliminar etapa</button>
              </>}
          </div>}
      </div>
      <div className={"kan-col-body" + (isOver ? " is-over" : "")}
           onDragOver={(e) => { e.preventDefault(); setHoverStage(stage.id); if (dragId && calls.length === 0) setOverIndex(0); }}
           onDragLeave={(e) => { if (e.currentTarget === e.target) { setHoverStage(null); setOverIndex(null); } }}
           onDrop={(e) => {
             e.preventDefault(); setHoverStage(null);
             if (dragId) {
               const beforeId = (overIndex != null && overIndex < calls.length) ? calls[overIndex].id : null;
               onDrop(dragId, stage.id, beforeId);
             }
             setOverIndex(null); setDragId(null);
           }}>
        {calls.map((c, i) =>
          <div className="kan-card-slot" key={c.id}
               style={{
                 marginTop: (dragId && dragId !== c.id && overIndex === i) ? 50 : undefined,
                 marginBottom: (dragId && overIndex === calls.length && i === calls.length - 1) ? 50 : undefined,
               }}
               onDragOver={(e) => {
                 if (!dragId) return;
                 e.preventDefault();
                 const r = e.currentTarget.getBoundingClientRect();
                 setOverIndex(e.clientY > r.top + r.height / 2 ? i + 1 : i);
               }}>
            <KanCard c={c} showCloser={showCloser} onOpen={onOpen} justLanded={justMovedId === c.id}
                     onDragStart={(e, id) => setDragId(id)} onDragEnd={() => { setDragId(null); setHoverStage(null); setOverIndex(null); }}
                     isDragging={dragId === c.id}/>
          </div>)}
        {calls.length === 0 &&
          <div style={{ color: "var(--text-3)", fontSize: 12, padding: "16px 8px", textAlign: "center" }}>Sin llamadas en esta etapa</div>}
      </div>
    </div>);
}

function NewStageTile({ onAdd }) {
  const [open, setOpen] = useState(false);
  const [name, setName] = useState("");
  const [color, setColor] = useState(STAGE_COLOR_SWATCHES[0]);
  const inputRef = useRef(null);
  useEffect(() => { if (open && inputRef.current) inputRef.current.focus(); }, [open]);

  const commit = () => {
    const n = name.trim();
    if (!n) return;
    onAdd(n, color); setName(""); setColor(STAGE_COLOR_SWATCHES[0]); setOpen(false);
  };

  if (!open) {
    return (
      <button className="kan-add-col" onClick={() => setOpen(true)}>
        <IconPlus size={20}/> Añadir etapa <small>Personaliza este pipeline</small>
      </button>);
  }
  return (
    <div className="new-stage-form" onKeyDown={(e) => { if (e.key === "Escape") setOpen(false); if (e.key === "Enter" && name.trim()) commit(); }}>
      <div>
        <div className="label">Nombre de la etapa</div>
        <input ref={inputRef} value={name} onChange={(e) => setName(e.target.value)} placeholder="Ej. Seguimiento" style={{ width: "100%", marginTop: 4 }}/>
      </div>
      <div>
        <div className="label" style={{ marginBottom: 6 }}>Color</div>
        <div className="swatch-row">
          {STAGE_COLOR_SWATCHES.map((c) => <span key={c} className="sw" data-active={c === color ? "true" : undefined} style={{ background: c }} onClick={() => setColor(c)}/>)}
        </div>
      </div>
      <div className="actions">
        <button className="crm-btn" onClick={() => setOpen(false)}>Cancelar</button>
        <button className="crm-btn" data-variant="primary" onClick={commit} disabled={!name.trim()}>Crear etapa</button>
      </div>
    </div>);
}

function DeleteStageConfirm({ stage, stages, count, onCancel, onConfirm }) {
  const others = stages.filter((s) => s.id !== stage.id);
  const [moveTo, setMoveTo] = useState(others[0]?.id || "");
  return (
    <div className="confirm-overlay" onClick={onCancel}>
      <div className="confirm-modal" onClick={(e) => e.stopPropagation()}>
        <h3>Eliminar etapa "{stage.label}"</h3>
        {count > 0 ?
          <>
            <p>Esta etapa tiene <strong>{count} llamada{count === 1 ? "" : "s"}</strong>. Muévelas a otra etapa antes de eliminar.</p>
            <select value={moveTo} onChange={(e) => setMoveTo(e.target.value)}>
              {others.map((s) => <option key={s.id} value={s.id}>Mover a "{s.label}"</option>)}
            </select>
          </> :
          <p>Esta etapa está vacía. Se eliminará permanentemente.</p>}
        <div className="actions">
          <button className="crm-btn" onClick={onCancel}>Cancelar</button>
          <button className="crm-btn" data-variant="primary" style={{ background: "var(--danger)", borderColor: "var(--danger)" }}
                  onClick={() => onConfirm(moveTo)} disabled={count > 0 && !moveTo}>Eliminar etapa</button>
        </div>
      </div>
    </div>);
}

function PipelineView({
  calls, stages, onOpen, onMove, filters, setFilters, showCloser, justMovedId,
  onAddStage, onRenameStage, onRecolorStage, onDeleteStage, onMoveStage, onReorderStages, onExport
}) {
  const [dragId, setDragId] = useState(null);
  const [hoverStage, setHoverStage] = useState(null);
  const [stageDragId, setStageDragId] = useState(null);
  const [stageHoverId, setStageHoverId] = useState(null);
  const [confirmDelete, setConfirmDelete] = useState(null);
  const scrollRef = useRef(null);
  const [scrollState, setScrollState] = useState({ left: false, right: false });
  const SOURCES = window.REVOLVR_DATA.SOURCES;

  const updateScrollState = () => {
    const el = scrollRef.current;
    if (!el) return;
    setScrollState({ left: el.scrollLeft > 4, right: el.scrollLeft + el.clientWidth < el.scrollWidth - 4 });
  };
  useEffect(() => {
    updateScrollState();
    const el = scrollRef.current;
    if (!el) return;
    el.addEventListener("scroll", updateScrollState);
    window.addEventListener("resize", updateScrollState);
    return () => { el.removeEventListener("scroll", updateScrollState); window.removeEventListener("resize", updateScrollState); };
  }, [stages.length]);

  const scrollBy = (dx) => scrollRef.current?.scrollBy({ left: dx, behavior: "smooth" });

  const filtered = calls.filter((c) => {
    if (filters.source && c.utm.source !== filters.source) return false;
    if (filters.dateRange && (filters.dateRange.from || filters.dateRange.to)) {
      const d = c.createdAt;
      if (filters.dateRange.from && d < filters.dateRange.from) return false;
      if (filters.dateRange.to) { const end = new Date(filters.dateRange.to); end.setHours(23, 59, 59, 999); if (d > end) return false; }
    }
    if (filters.q) {
      const q = filters.q.toLowerCase();
      if (!`${c.name} ${c.email} ${c.form.industria} ${c.eventType}`.toLowerCase().includes(q)) return false;
    }
    return true;
  });

  const byStage = {};
  stages.forEach((s) => byStage[s.id] = []);
  filtered.forEach((c) => byStage[c.stage]?.push(c));

  const handleConfirmDelete = (moveTo) => { onDeleteStage(confirmDelete.stage.id, moveTo); setConfirmDelete(null); };

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }}>
      <div className="kanban-toolbar">
        {PERIODS.map((p) => {
          const active = matchingPeriodId(filters.dateRange) === p.id;
          return <Chip key={p.id} active={active} onClick={() => setFilters({ ...filters, dateRange: active ? null : periodToRange(p.id) })}>{p.label}</Chip>;
        })}
        <DateRangeFilter value={filters.dateRange} onChange={(r) => setFilters({ ...filters, dateRange: r })}/>
        <span style={{ width: 1, height: 16, background: "var(--border)", margin: "0 2px" }}/>
        <select className="crm-btn" value={filters.source || ""} onChange={(e) => setFilters({ ...filters, source: e.target.value || null })}>
          <option value="">Fuente: todas</option>
          {Object.entries(SOURCES).map(([k, v]) => <option key={k} value={k}>{v.label}</option>)}
        </select>
        <div className="spacer"/>
        <span style={{ fontSize: 12, color: "var(--text-3)" }}>{filtered.length} de {calls.length} llamadas</span>
        <button className="crm-btn" onClick={() => onExport(filtered)}>Exportar CSV</button>
      </div>

      <div style={{ position: "relative", flex: 1, minHeight: 0 }}>
        <div className="pipeline-scroll" ref={scrollRef}>
          <div className="kanban">
            {stages.map((s, idx) =>
              <KanColumn key={s.id} stage={s} calls={byStage[s.id]} showCloser={showCloser} justMovedId={justMovedId}
                onOpen={onOpen} onDrop={onMove} dragId={dragId} setDragId={setDragId}
                hoverStage={hoverStage} setHoverStage={setHoverStage}
                onRename={onRenameStage} onRecolor={onRecolorStage}
                onDelete={(id) => setConfirmDelete({ stage: stages.find((x) => x.id === id), count: byStage[id]?.length || 0 })}
                onMove={onMoveStage} isFirst={idx === 0} isLast={idx === stages.length - 1}
                stageDragId={stageDragId} setStageDragId={setStageDragId}
                stageHoverId={stageHoverId} setStageHoverId={setStageHoverId} onReorderStages={onReorderStages}/>)}
            <NewStageTile onAdd={onAddStage}/>
          </div>
        </div>
        <button className="pipeline-nav-btn" data-side="left" onClick={() => scrollBy(-320)} disabled={!scrollState.left}><IconChevR size={18} style={{ transform: "rotate(180deg)" }}/></button>
        <button className="pipeline-nav-btn" data-side="right" onClick={() => scrollBy(+320)} disabled={!scrollState.right}><IconChevR size={18}/></button>
      </div>

      {confirmDelete &&
        <DeleteStageConfirm stage={confirmDelete.stage} stages={stages} count={confirmDelete.count}
          onCancel={() => setConfirmDelete(null)} onConfirm={handleConfirmDelete}/>}
    </div>);
}

function Chip({ children, active, onClick }) {
  return <button className="chip" data-active={active ? "true" : undefined} onClick={onClick}>{children}</button>;
}

// ---- Period presets ----------------------------------------------
const PERIODS = [
  { id: "7d",  label: "7 días",   days: 7 },
  { id: "14d", label: "14 días",  days: 14 },
  { id: "30d", label: "30 días",  days: 30 },
  { id: "90d", label: "90 días",  days: 90 },
];
function periodToRange(id) {
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const p = PERIODS.find((x) => x.id === id);
  if (!p) return null;
  return { from: new Date(today.getTime() - p.days * 86400000), to: today };
}
function sameDay(a, b) { return a && b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate(); }
function matchingPeriodId(range) {
  if (!range || !range.from || !range.to) return null;
  for (const p of PERIODS) { const pr = periodToRange(p.id); if (sameDay(range.from, pr.from) && sameDay(range.to, pr.to)) return p.id; }
  return null;
}

// ---- Date range picker -------------------------------------------
function DateRangeFilter({ value, onChange }) {
  const [open, setOpen] = useState(false);
  const today = new Date(); today.setHours(0, 0, 0, 0);
  const [viewMonth, setViewMonth] = useState(() => new Date(today.getFullYear(), today.getMonth(), 1));
  const ref = useRef(null);

  useEffect(() => {
    if (!open) return;
    const onDown = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", onDown);
    return () => document.removeEventListener("mousedown", onDown);
  }, [open]);

  const fmt = (d) => d ? d.toLocaleDateString("es-ES", { day: "numeric", month: "short" }) : "";
  const hasValue = value && (value.from || value.to);
  const label = hasValue ? (value.to ? `${fmt(value.from)} – ${fmt(value.to)}` : `Desde ${fmt(value.from)}`) : "Por fecha";

  const daysInMonth = new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 0).getDate();
  const firstDay = new Date(viewMonth.getFullYear(), viewMonth.getMonth(), 1).getDay();
  const offset = (firstDay + 6) % 7;
  const monthName = viewMonth.toLocaleDateString("es-ES", { month: "long", year: "numeric" });

  const cells = [];
  for (let i = 0; i < offset; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(new Date(viewMonth.getFullYear(), viewMonth.getMonth(), d));

  const sd = (a, b) => a && b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
  const inRange = (d) => value && value.from && value.to && d > value.from && d < value.to;

  const pickDate = (d) => {
    if (!value || !value.from || (value.from && value.to)) onChange({ from: d, to: null });
    else if (value.from && !value.to) {
      if (d < value.from) onChange({ from: d, to: value.from });
      else if (sd(d, value.from)) onChange({ from: d, to: d });
      else onChange({ from: value.from, to: d });
    }
  };

  return (
    <div className="date-filter" ref={ref}>
      <button className="crm-btn" data-variant={hasValue ? "primary" : undefined} onClick={() => setOpen((v) => !v)}>
        <IconCalendar size={12}/> {label}
        {hasValue && <span className="date-clear" onClick={(e) => { e.stopPropagation(); onChange(null); }} title="Limpiar">×</span>}
      </button>
      {open &&
        <div className="date-popover">
          <div className="dp-presets">
            {[{ label: "Hoy", days: 0 }, { label: "Últimos 7 días", days: 7 }, { label: "Últimos 30 días", days: 30 }].map((p) =>
              <button key={p.label} className="dp-preset" onClick={() => onChange({ from: new Date(today.getTime() - p.days * 86400000), to: new Date(today) })}>{p.label}</button>)}
          </div>
          <div className="dp-head">
            <button className="dp-nav" onClick={() => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() - 1, 1))}>‹</button>
            <span className="dp-title">{monthName}</span>
            <button className="dp-nav" onClick={() => setViewMonth(new Date(viewMonth.getFullYear(), viewMonth.getMonth() + 1, 1))}>›</button>
          </div>
          <div className="dp-grid dp-grid-head">{["L", "M", "X", "J", "V", "S", "D"].map((d) => <span key={d}>{d}</span>)}</div>
          <div className="dp-grid">
            {cells.map((d, i) => d ?
              <button key={i} className="dp-day" data-from={sd(d, value?.from) ? "true" : undefined} data-to={sd(d, value?.to) ? "true" : undefined}
                      data-between={inRange(d) ? "true" : undefined} data-today={sd(d, today) ? "true" : undefined} onClick={() => pickDate(d)}>{d.getDate()}</button> :
              <span key={i} className="dp-empty"></span>)}
          </div>
          <div className="dp-actions">
            <button className="crm-btn" onClick={() => onChange(null)}>Limpiar</button>
            <button className="crm-btn" data-variant="primary" onClick={() => setOpen(false)}>Aplicar</button>
          </div>
        </div>}
    </div>);
}

Object.assign(window, { PipelineView, Chip, StageDot, DateRangeFilter, SourceBadge, shortWhen, PERIODS, paymentState });
