import { useRef, useEffect, useState, useCallback } from 'react';
import { format } from 'date-fns';
import { Pencil, Trash2 } from 'lucide-react';
import { Badge } from '@/components/ui/badge';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from '@/components/ui/context-menu';

export interface GanttCheckpoint {
  id: string;
  title: string;
  date: number; // unix timestamp ms
  projectId: string;
  projectName?: string;
  isAiSuggested: number;
  isApproved: number;
}

interface GanttChartProps {
  checkpoints: GanttCheckpoint[];
  startDate: Date;
  endDate: Date;
  onDelete?: (id: string) => void;
  onEdit?: (checkpoint: GanttCheckpoint) => void;
  onToggleApproval?: (id: string, currentApproved: number) => void;
}

const HEADER_HEIGHT = 30;
const BASELINE_Y = 70;
const BASELINE_HEIGHT = 8;
const SVG_HEIGHT = 110;
const DOT_RADIUS = 10;
const PADDING_X = 40;

function getMonthsBetween(start: Date, end: Date): Date[] {
  const months: Date[] = [];
  const current = new Date(start.getFullYear(), start.getMonth(), 1);
  while (current <= end) {
    months.push(new Date(current));
    current.setMonth(current.getMonth() + 1);
  }
  return months;
}

function dateToX(date: Date, start: Date, end: Date, width: number): number {
  const totalMs = end.getTime() - start.getTime();
  if (totalMs <= 0) return PADDING_X;
  const ratio = (date.getTime() - start.getTime()) / totalMs;
  return PADDING_X + ratio * (width - PADDING_X * 2);
}

export function GanttChart({
  checkpoints,
  startDate,
  endDate,
  onDelete,
  onEdit,
  onToggleApproval,
}: GanttChartProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const [width, setWidth] = useState(600);

  useEffect(() => {
    const el = containerRef.current;
    if (!el) return;

    const observer = new ResizeObserver((entries) => {
      const entry = entries[0];
      if (entry) {
        setWidth(entry.contentRect.width);
      }
    });
    observer.observe(el);
    return () => observer.disconnect();
  }, []);

  const months = getMonthsBetween(startDate, endDate);
  const todayX = dateToX(new Date(), startDate, endDate, width);
  const todayVisible = todayX >= PADDING_X && todayX <= width - PADDING_X;

  return (
    <div ref={containerRef} className="w-full overflow-hidden">
      <svg width={width} height={SVG_HEIGHT} className="select-none overflow-visible">
        {/* Month labels */}
        {months.map((month) => {
          const x = dateToX(month, startDate, endDate, width);
          return (
            <g key={month.toISOString()}>
              <text
                x={x}
                y={HEADER_HEIGHT - 8}
                textAnchor="middle"
                className="fill-muted-foreground"
                fontSize={12}
                fontFamily="Geist, sans-serif"
              >
                {format(month, 'MMM yyyy')}
              </text>
              <line
                x1={x}
                y1={HEADER_HEIGHT}
                x2={x}
                y2={BASELINE_Y + 14}
                stroke="var(--border)"
                strokeWidth={1}
                strokeDasharray="4 4"
              />
            </g>
          );
        })}

        {/* Baseline — thick rounded bar */}
        <rect
          x={PADDING_X}
          y={BASELINE_Y - BASELINE_HEIGHT / 2}
          width={Math.max(0, width - PADDING_X * 2)}
          height={BASELINE_HEIGHT}
          rx={BASELINE_HEIGHT / 2}
          fill="var(--border)"
        />

        {/* Today marker — dashed line */}
        {todayVisible && (
          <line
            x1={todayX}
            y1={HEADER_HEIGHT}
            x2={todayX}
            y2={BASELINE_Y + 14}
            stroke="var(--destructive)"
            strokeWidth={1.5}
            strokeDasharray="4 2"
          />
        )}

        {/* Today marker — Badge label via foreignObject */}
        {todayVisible && (
          <foreignObject
            x={todayX - 30}
            y={BASELINE_Y + 12}
            width={60}
            height={28}
            className="overflow-visible"
          >
            <div className="flex justify-center">
              <Badge variant="outline" className="text-[10px] px-1.5 py-0 border-destructive text-destructive">
                Today
              </Badge>
            </div>
          </foreignObject>
        )}

        {/* Checkpoint dots */}
        {checkpoints.map((cp) => {
          const cx = dateToX(new Date(cp.date), startDate, endDate, width);
          return (
            <CheckpointDot
              key={cp.id}
              checkpoint={cp}
              cx={cx}
              onDelete={onDelete}
              onEdit={onEdit}
              onToggleApproval={onToggleApproval}
            />
          );
        })}
      </svg>
    </div>
  );
}

function getStatusLabel(checkpoint: GanttCheckpoint): { text: string; className: string } {
  if (checkpoint.isApproved === 0) {
    return { text: 'Pending', className: 'bg-muted text-muted-foreground' };
  }
  if (checkpoint.date < Date.now()) {
    return { text: 'Completed', className: 'bg-chart-2/15 text-chart-2' };
  }
  return { text: 'To Do', className: 'bg-primary/10 text-primary' };
}

function CheckpointDot({
  checkpoint,
  cx,
  onDelete,
  onEdit,
  onToggleApproval,
}: {
  checkpoint: GanttCheckpoint;
  cx: number;
  onDelete?: (id: string) => void;
  onEdit?: (checkpoint: GanttCheckpoint) => void;
  onToggleApproval?: (id: string, currentApproved: number) => void;
}) {
  const [hovered, setHovered] = useState(false);
  const hoverTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);

  const handleMouseEnter = useCallback(() => {
    if (hoverTimeout.current) clearTimeout(hoverTimeout.current);
    hoverTimeout.current = setTimeout(() => setHovered(true), 200);
  }, []);

  const handleMouseLeave = useCallback(() => {
    if (hoverTimeout.current) clearTimeout(hoverTimeout.current);
    hoverTimeout.current = setTimeout(() => setHovered(false), 150);
  }, []);

  const isPending = checkpoint.isApproved === 0;
  const isPast = checkpoint.date < Date.now();
  const fill = isPending ? 'none' : (isPast ? 'var(--chart-2)' : 'var(--primary)');
  const stroke = isPending ? 'var(--muted-foreground)' : 'none';
  const strokeDasharray = isPending ? '3 2' : undefined;
  const status = getStatusLabel(checkpoint);

  const dotSize = DOT_RADIUS * 2 + 2;
  const hitArea = dotSize + 8;

  const dotSvg = (
    <svg width={dotSize} height={dotSize} className="shrink-0">
      <circle
        cx={DOT_RADIUS + 1}
        cy={DOT_RADIUS + 1}
        r={DOT_RADIUS}
        fill={fill}
        stroke={stroke || 'var(--primary)'}
        strokeWidth={isPending ? 1.5 : 0}
        strokeDasharray={strokeDasharray}
      />
    </svg>
  );

  return (
    <foreignObject
      x={cx - hitArea / 2}
      y={BASELINE_Y - hitArea / 2}
      width={hitArea}
      height={hitArea}
      className="overflow-visible"
    >
      <ContextMenu>
        <Popover open={hovered}>
          <ContextMenuTrigger asChild>
            <PopoverTrigger asChild>
              <button
                className="flex items-center justify-center w-full h-full focus:outline-none cursor-pointer"
                type="button"
                onClick={() => onToggleApproval?.(checkpoint.id, checkpoint.isApproved)}
                onMouseEnter={handleMouseEnter}
                onMouseLeave={handleMouseLeave}
              >
                {dotSvg}
              </button>
            </PopoverTrigger>
          </ContextMenuTrigger>

          <PopoverContent
            className="w-52 p-3 pointer-events-none"
            side="top"
            sideOffset={8}
            onOpenAutoFocus={(e) => e.preventDefault()}
          >
            <div className="flex flex-col gap-1.5">
              <div className="flex items-center justify-between gap-2">
                <span className="font-semibold text-sm leading-snug truncate">
                  {checkpoint.title}
                </span>
                <Badge variant="secondary" className={`text-[10px] px-1.5 py-0 shrink-0 ${status.className}`}>
                  {status.text}
                </Badge>
              </div>
              <span className="text-xs text-muted-foreground">
                {format(new Date(checkpoint.date), 'PPP')}
              </span>
              {checkpoint.projectName && (
                <span className="text-xs text-muted-foreground">
                  {checkpoint.projectName}
                </span>
              )}
            </div>
          </PopoverContent>
        </Popover>

        <ContextMenuContent>
          <ContextMenuItem onSelect={() => onEdit?.(checkpoint)}>
            <Pencil className="h-4 w-4 mr-2" />
            Edit Checkpoint
          </ContextMenuItem>
          <ContextMenuItem
            onSelect={() => onDelete?.(checkpoint.id)}
            className="text-destructive focus:text-destructive"
          >
            <Trash2 className="h-4 w-4 mr-2" />
            Delete Checkpoint
          </ContextMenuItem>
        </ContextMenuContent>
      </ContextMenu>
    </foreignObject>
  );
}
