import { useState } from 'react';

interface Opp {
  id: string;
  title: string;
  amountEstimated: number;
  stage: string;
  contactName: string;
  boardRank: number;
}

interface Props {
  initial: Opp[];
  stages: string[];
  stageLabels: Record<string, string>;
}

const peso = new Intl.NumberFormat('es-MX', {
  style: 'currency',
  currency: 'MXN',
  maximumFractionDigits: 0,
});

export default function PipelineBoard({ initial, stages, stageLabels }: Props) {
  const [opps, setOpps] = useState(initial);
  const [dragId, setDragId] = useState<string | null>(null);
  const [overStage, setOverStage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const colOpps = (stage: string) =>
    opps.filter((o) => o.stage === stage).sort((a, b) => b.boardRank - a.boardRank);
  const colTotal = (stage: string) => colOpps(stage).reduce((s, o) => s + o.amountEstimated, 0);
  const topRank = () => Math.max(0, ...opps.map((o) => o.boardRank)) + 1;

  function patch(prev: Opp[], next: Opp[], body: Record<string, unknown>, id: string, url: string) {
    setOpps(next);
    setError(null);
    fetch(url, { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) })
      .then((r) => r.json())
      .then((j) => {
        if (!j.ok) {
          setOpps(prev);
          setError(j.error || 'No se pudo guardar el cambio.');
        }
      })
      .catch(() => {
        setOpps(prev);
        setError('Error de red. Intenta de nuevo.');
      });
  }

  // Mover a otra etapa → queda al tope de esa columna.
  function moveStage(id: string, stage: string) {
    const opp = opps.find((o) => o.id === id);
    if (!opp || opp.stage === stage) return;
    let reason: string | undefined;
    if (stage === 'perdido') {
      reason = window.prompt('Motivo de pérdida (obligatorio):') || undefined;
      if (!reason) return;
    }
    const rank = topRank();
    const prev = opps;
    const next = opps.map((o) => (o.id === id ? { ...o, stage, boardRank: rank } : o));
    patch(prev, next, { stage, reason }, id, `/api/crm/opportunities/${id}/change-stage`);
  }

  // Reordenar dentro de la misma columna: insertar ARRIBA de `targetId`.
  function reorderAbove(id: string, targetId: string) {
    if (id === targetId) return;
    const opp = opps.find((o) => o.id === id);
    const target = opps.find((o) => o.id === targetId);
    if (!opp || !target || opp.stage !== target.stage) return;
    const col = colOpps(target.stage); // desc por rank
    const idx = col.findIndex((o) => o.id === targetId);
    const aboveRank = idx > 0 ? col[idx - 1]!.boardRank : target.boardRank + 2;
    const newRank = (aboveRank + target.boardRank) / 2;
    const prev = opps;
    const next = opps.map((o) => (o.id === id ? { ...o, boardRank: newRank } : o));
    patch(prev, next, { boardRank: newRank }, id, `/api/crm/opportunities/${id}`);
  }

  // Soltar en zona vacía de la columna → al tope.
  function moveToTop(id: string, stage: string) {
    const opp = opps.find((o) => o.id === id);
    if (!opp) return;
    if (opp.stage !== stage) return moveStage(id, stage);
    const rank = topRank();
    const prev = opps;
    const next = opps.map((o) => (o.id === id ? { ...o, boardRank: rank } : o));
    patch(prev, next, { boardRank: rank }, id, `/api/crm/opportunities/${id}`);
  }

  return (
    <div>
      {error && <p className="notice" style={{ borderColor: 'var(--pf-danger)', color: 'var(--pf-danger)', marginBottom: 12 }}>{error}</p>}
      <p className="muted" style={{ fontSize: '.9rem' }}>
        Arrastra para mover entre columnas (cae al tope) o reordenar verticalmente dentro de una columna.
      </p>

      <div style={{ display: 'flex', gap: 12, overflowX: 'auto', padding: '16px 0' }}>
        {stages.map((stage) => {
          const items = colOpps(stage);
          const isOver = overStage === stage;
          return (
            <div key={stage} style={{ minWidth: 260, flex: '0 0 260px' }}>
              <div className="card" style={{ padding: 12, background: 'var(--pf-surface-2)' }}>
                <strong style={{ fontSize: '.95rem' }}>{stageLabels[stage] ?? stage}</strong>
                <span className="muted" style={{ fontSize: '.8rem' }}> · {items.length} · {peso.format(colTotal(stage))}</span>
              </div>

              <div
                onDragOver={(e) => { e.preventDefault(); setOverStage(stage); }}
                onDragLeave={() => setOverStage((s) => (s === stage ? null : s))}
                onDrop={(e) => {
                  e.preventDefault();
                  setOverStage(null);
                  if (dragId) moveToTop(dragId, stage);
                  setDragId(null);
                }}
                style={{
                  display: 'flex', flexDirection: 'column', gap: 8, marginTop: 8, minHeight: 140, padding: 4,
                  borderRadius: 10,
                  background: isOver ? 'rgba(46,46,214,.08)' : 'transparent',
                  outline: isOver ? '1px dashed var(--pf-accent)' : 'none',
                }}
              >
                {items.map((o) => (
                  <div
                    key={o.id}
                    draggable
                    onDragStart={() => setDragId(o.id)}
                    onDragEnd={() => { setDragId(null); setOverStage(null); }}
                    onDragOver={(e) => { e.preventDefault(); }}
                    onDrop={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      setOverStage(null);
                      if (dragId && dragId !== o.id) {
                        const drag = opps.find((d) => d.id === dragId);
                        if (drag && drag.stage === o.stage) reorderAbove(dragId, o.id);
                        else if (drag) moveStage(dragId, o.stage);
                      }
                      setDragId(null);
                    }}
                    className="card"
                    style={{ padding: 12, cursor: 'grab', opacity: dragId === o.id ? 0.5 : 1 }}
                  >
                    <a href={`/crm/oportunidades/${o.id}`} style={{ fontWeight: 600, fontSize: '.9rem', display: 'block' }}>
                      {o.title}
                    </a>
                    <div className="muted" style={{ fontSize: '.78rem', marginTop: 4 }}>
                      {o.contactName} · {peso.format(o.amountEstimated)}
                    </div>
                  </div>
                ))}
                {items.length === 0 && (
                  <div className="muted" style={{ fontSize: '.78rem', padding: 8 }}>Suelta aquí</div>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}
