import { useState, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
import {
  DndContext,
  DragOverlay,
  PointerSensor,
  useSensor,
  useSensors,
  useDroppable,
  useDraggable,
  type DragEndEvent,
  type DragStartEvent,
} from '@dnd-kit/core';
import { useDeals, usePipelines, useUpdateDeal } from '../hooks';
import type { Deal, DealStatus, Pipeline, PipelineStage } from '../types';
import styles from './KanbanPage.module.css';

// ============================================================
//  Constants
// ============================================================

const STATUS_COLORS: Record<DealStatus, { bg: string; color: string }> = {
  OPEN: { bg: '#dbeafe', color: '#1e40af' },
  WON: { bg: '#d1fae5', color: '#065f46' },
  LOST: { bg: '#fee2e2', color: '#991b1b' },
};

const STATUS_LABELS: Record<DealStatus, string> = {
  OPEN: 'Offen',
  WON: 'Gewonnen',
  LOST: 'Verloren',
};

const currencyFormatter = new Intl.NumberFormat('de-DE', {
  style: 'currency',
  currency: 'EUR',
});

// ============================================================
//  DealCard (draggable)
// ============================================================

interface DealCardProps {
  deal: Deal;
  isDragging?: boolean;
  onNavigate: (id: string) => void;
}

function DealCard({ deal, isDragging = false, onNavigate }: DealCardProps) {
  const { attributes, listeners, setNodeRef, transform } = useDraggable({
    id: deal.id,
    data: { stageId: deal.stageId },
  });

  const style = transform
    ? {
        transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
        opacity: isDragging ? 0.4 : 1,
        zIndex: isDragging ? 1000 : undefined,
      }
    : { opacity: isDragging ? 0.4 : 1 };

  return (
    <div
      ref={setNodeRef}
      style={style}
      className={styles.dealCard}
      {...listeners}
      {...attributes}
    >
      <div className={styles.dealCardTitle} onClick={() => onNavigate(deal.id)}>
        {deal.title}
      </div>
      {deal.company && (
        <div className={styles.dealCardMeta}>{deal.company.name}</div>
      )}
      {deal.contact && (
        <div className={styles.dealCardMeta}>
          {[deal.contact.firstName, deal.contact.lastName].filter(Boolean).join(' ') ||
            deal.contact.companyName}
        </div>
      )}
      <div className={styles.dealCardFooter}>
        {deal.value && (
          <span className={styles.dealCardValue}>
            {currencyFormatter.format(Number(deal.value))}
          </span>
        )}
        <span
          className={styles.dealCardStatus}
          style={{
            background: STATUS_COLORS[deal.status].bg,
            color: STATUS_COLORS[deal.status].color,
          }}
        >
          {STATUS_LABELS[deal.status]}
        </span>
      </div>
    </div>
  );
}

// DealCard ohne DnD (für DragOverlay)
function DealCardStatic({ deal }: { deal: Deal }) {
  return (
    <div className={`${styles.dealCard} ${styles.dealCardOverlay}`}>
      <div className={styles.dealCardTitle}>{deal.title}</div>
      {deal.company && (
        <div className={styles.dealCardMeta}>{deal.company.name}</div>
      )}
      <div className={styles.dealCardFooter}>
        {deal.value && (
          <span className={styles.dealCardValue}>
            {currencyFormatter.format(Number(deal.value))}
          </span>
        )}
        <span
          className={styles.dealCardStatus}
          style={{
            background: STATUS_COLORS[deal.status].bg,
            color: STATUS_COLORS[deal.status].color,
          }}
        >
          {STATUS_LABELS[deal.status]}
        </span>
      </div>
    </div>
  );
}

// ============================================================
//  KanbanColumn (droppable)
// ============================================================

interface KanbanColumnProps {
  stage: PipelineStage;
  deals: Deal[];
  isOver: boolean;
  onNavigate: (id: string) => void;
  activeDealId: string | null;
}

function KanbanColumn({ stage, deals, isOver, onNavigate, activeDealId }: KanbanColumnProps) {
  const { setNodeRef } = useDroppable({ id: stage.id });

  const totalValue = deals
    .filter((d) => d.status === 'OPEN')
    .reduce((sum, d) => sum + (d.value ? Number(d.value) : 0), 0);

  return (
    <div
      ref={setNodeRef}
      className={`${styles.column} ${isOver ? styles.columnOver : ''}`}
    >
      <div className={styles.columnHeader}>
        <div className={styles.columnHeaderLeft}>
          <span
            className={styles.columnDot}
            style={{ background: stage.color || 'var(--color-primary)' }}
          />
          <span className={styles.columnName}>{stage.name}</span>
          <span className={styles.columnCount}>{deals.length}</span>
        </div>
        {totalValue > 0 && (
          <span className={styles.columnValue}>
            {currencyFormatter.format(totalValue)}
          </span>
        )}
      </div>

      <div className={styles.columnBody}>
        {deals.map((deal) => (
          <DealCard
            key={deal.id}
            deal={deal}
            isDragging={deal.id === activeDealId}
            onNavigate={onNavigate}
          />
        ))}
        {deals.length === 0 && (
          <div className={styles.columnEmpty}>Keine Vorgänge</div>
        )}
      </div>
    </div>
  );
}

// ============================================================
//  KanbanPage
// ============================================================

export function KanbanPage() {
  const navigate = useNavigate();
  const { data: pipelinesData } = usePipelines();
  const pipelines: Pipeline[] = pipelinesData?.data ?? [];

  const defaultPipeline = pipelines.find((p) => p.isDefault) ?? pipelines[0];
  const [selectedPipelineId, setSelectedPipelineId] = useState<string>('');
  const [showClosed, setShowClosed] = useState(false);
  const [activeDealId, setActiveDealId] = useState<string | null>(null);
  const [overStageId, setOverStageId] = useState<string | null>(null);

  const pipelineId = selectedPipelineId || defaultPipeline?.id || '';
  const selectedPipeline = pipelines.find((p) => p.id === pipelineId);

  const { data: dealsData } = useDeals(
    pipelineId ? { pipelineId, pageSize: 500 } : { pageSize: 0 },
  );
  const allDeals: Deal[] = dealsData?.data ?? [];
  const updateDeal = useUpdateDeal();

  // Deals nach Status filtern
  const visibleDeals = useMemo(
    () =>
      showClosed
        ? allDeals
        : allDeals.filter((d) => d.status === 'OPEN'),
    [allDeals, showClosed],
  );

  // Optimistische Positionen: localStageMap überschreibt deal.stageId während Drag
  const [localStageMap, setLocalStageMap] = useState<Record<string, string>>({});

  const dealsByStage = useMemo(() => {
    const map: Record<string, Deal[]> = {};
    const stages = selectedPipeline?.stages ?? [];
    for (const s of stages) map[s.id] = [];
    for (const deal of visibleDeals) {
      const effectiveStageId = localStageMap[deal.id] ?? deal.stageId;
      if (map[effectiveStageId]) {
        map[effectiveStageId].push(deal);
      } else if (map[deal.stageId]) {
        map[deal.stageId].push(deal);
      }
    }
    return map;
  }, [visibleDeals, selectedPipeline, localStageMap]);

  const activeDeal = allDeals.find((d) => d.id === activeDealId) ?? null;

  // Sensors
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: { distance: 8 },
    }),
  );

  const handleDragStart = (event: DragStartEvent) => {
    setActiveDealId(String(event.active.id));
  };

  const handleDragOver = (event: { over: { id: string } | null }) => {
    setOverStageId(event.over ? String(event.over.id) : null);
  };

  const handleDragEnd = (event: DragEndEvent) => {
    const dealId = String(event.active.id);
    const targetStageId = event.over ? String(event.over.id) : null;
    const sourceStageId = (event.active.data.current as { stageId: string } | undefined)?.stageId;

    setActiveDealId(null);
    setOverStageId(null);

    if (!targetStageId || targetStageId === sourceStageId) return;

    // Optimistisch verschieben
    setLocalStageMap((prev) => ({ ...prev, [dealId]: targetStageId }));

    updateDeal.mutate(
      { id: dealId, data: { stageId: targetStageId } },
      {
        onError: () => {
          // Bei Fehler: zurücksetzen
          setLocalStageMap((prev) => {
            const next = { ...prev };
            delete next[dealId];
            return next;
          });
        },
        onSuccess: () => {
          // Nach Erfolg: localStageMap bereinigen (React Query invalidiert den Cache)
          setLocalStageMap((prev) => {
            const next = { ...prev };
            delete next[dealId];
            return next;
          });
        },
      },
    );
  };

  const stages = selectedPipeline?.stages ?? [];

  return (
    <div className={styles.page}>
      {/* Header */}
      <div className={styles.header}>
        <h1 className={styles.title}>Kanban-Board</h1>
        <div className={styles.controls}>
          <select
            className={styles.pipelineSelect}
            value={pipelineId}
            onChange={(e) => {
              setSelectedPipelineId(e.target.value);
              setLocalStageMap({});
            }}
          >
            {pipelines.map((p) => (
              <option key={p.id} value={p.id}>
                {p.name}
                {p.isDefault ? ' (Standard)' : ''}
              </option>
            ))}
          </select>

          <button
            className={`${styles.toggleBtn} ${showClosed ? styles.toggleBtnActive : ''}`}
            onClick={() => setShowClosed((v) => !v)}
          >
            Abgeschlossene anzeigen
          </button>
        </div>
      </div>

      {/* Board */}
      {!pipelineId ? (
        <p style={{ color: 'var(--color-text-muted)', fontSize: '0.9rem' }}>
          Keine Pipeline ausgewählt.
        </p>
      ) : (
        <DndContext
          sensors={sensors}
          onDragStart={handleDragStart}
          onDragOver={handleDragOver as Parameters<typeof DndContext>[0]['onDragOver']}
          onDragEnd={handleDragEnd}
        >
          <div className={styles.board}>
            {stages.map((stage) => (
              <KanbanColumn
                key={stage.id}
                stage={stage}
                deals={dealsByStage[stage.id] ?? []}
                isOver={overStageId === stage.id}
                onNavigate={(id) => navigate(`/crm/deals/${id}`)}
                activeDealId={activeDealId}
              />
            ))}
          </div>

          <DragOverlay dropAnimation={null}>
            {activeDeal ? <DealCardStatic deal={activeDeal} /> : null}
          </DragOverlay>
        </DndContext>
      )}
    </div>
  );
}
