import { useEffect, useMemo, useRef, useState } from 'react';
import {
  buildMilestoneTimeline,
  type TimelineMilestoneInput,
  type TimelineRangeFallback,
} from '../../lib/milestoneTimeline';

interface MilestoneTimelineProps {
  milestones: TimelineMilestoneInput[];
  fallback?: TimelineRangeFallback;
  selectedId?: string | null;
  onSelect?: (id: string) => void;
  title?: string;
  subtitle?: string;
  emptyMessage?: string;
  className?: string;
  preserveRowOrder?: boolean;
  /** 상시업무 — 시작·종료일 없는 단계는 게이지 미표시 */
  hideUndatedBars?: boolean;
}

export function MilestoneTimeline({
  milestones,
  fallback = {},
  selectedId,
  onSelect,
  title = '업무별 타임라인',
  subtitle,
  emptyMessage = '기간을 설정한 단계만 표시됩니다.',
  preserveRowOrder = false,
  hideUndatedBars = true,
  className = '',
}: MilestoneTimelineProps) {
  const model = useMemo(
    () => buildMilestoneTimeline(milestones, fallback, { preserveOrder: preserveRowOrder, hideUndatedBars }),
    [milestones, fallback, preserveRowOrder, hideUndatedBars],
  );

  const chartRef = useRef<HTMLDivElement>(null);
  const rowRefs = useRef<Map<string, HTMLDivElement>>(new Map());
  const measureRef = useRef<HTMLSpanElement>(null);
  const [expandedBar, setExpandedBar] = useState<{
    id: string;
    widthPx: number;
    leftPx: number;
  } | null>(null);

  const measureTitleWidth = (title: string) => {
    const el = measureRef.current;
    if (!el) return 0;
    el.textContent = title;
    return el.offsetWidth + 16;
  };

  const handleBarEnter = (
    row: { id: string; title: string; leftPct: number; widthPct: number },
    event: React.MouseEvent<HTMLButtonElement>,
  ) => {
    const chart = chartRef.current;
    if (!chart) return;

    const btn = event.currentTarget;
    const chartWidth = chart.clientWidth;
    const leftPx = (row.leftPct / 100) * chartWidth;
    const origWidthPx = btn.offsetWidth;
    const neededWidthPx = measureTitleWidth(row.title);

    if (neededWidthPx <= origWidthPx + 1) return;

    const widthPx = Math.min(chartWidth, neededWidthPx);
    const extra = widthPx - origWidthPx;
    let expandedLeftPx = leftPx - extra / 2;

    if (expandedLeftPx < 0) expandedLeftPx = 0;
    if (expandedLeftPx + widthPx > chartWidth) expandedLeftPx = chartWidth - widthPx;

    setExpandedBar({
      id: row.id,
      widthPx,
      leftPx: expandedLeftPx,
    });
  };

  useEffect(() => {
    if (!selectedId) return;
    const row = rowRefs.current.get(selectedId);
    const chart = chartRef.current;
    if (!row || !chart) return;

    const rowRect = row.getBoundingClientRect();
    const chartRect = chart.getBoundingClientRect();

    if (rowRect.top >= chartRect.top && rowRect.bottom <= chartRect.bottom) return;

    const delta =
      rowRect.top < chartRect.top
        ? rowRect.top - chartRect.top
        : rowRect.bottom - chartRect.bottom;

    chart.scrollBy({ top: delta, behavior: 'smooth' });
  }, [selectedId, model?.rows.length]);

  const rangeSubtitle =
    subtitle ?? (model ? `${model.rangeStartLabel} ~ ${model.rangeEndLabel}` : undefined);

  const rowGroups = useMemo(() => {
    if (!model) return [];
    const groups: Array<{
      milestoneId: string;
      title: string;
      progress: number;
      segments: (typeof model.rows)[number][];
    }> = [];
    const indexByMilestone = new Map<string, number>();
    for (const row of model.rows) {
      const idx = indexByMilestone.get(row.milestoneId);
      if (idx === undefined) {
        indexByMilestone.set(row.milestoneId, groups.length);
        groups.push({
          milestoneId: row.milestoneId,
          title: row.title,
          progress: row.progress,
          segments: [row],
        });
      } else {
        groups[idx].segments.push(row);
      }
    }
    return groups;
  }, [model]);

  return (
    <footer className={`milestone-timeline ${className}`.trim()}>
      <div className="milestone-timeline__head">
        <span className="milestone-timeline__title">{title}</span>
        {rangeSubtitle && (
          <span className="milestone-timeline__subtitle truncate">{rangeSubtitle}</span>
        )}
      </div>

      {!model ? (
        <p className="milestone-timeline__empty">{emptyMessage}</p>
      ) : (
        <div className="milestone-timeline__body">
          <div className="milestone-timeline__ticks" aria-hidden="true">
            {model.ticks.map((tick) => (
              <span
                key={`${tick.label}-${tick.leftPct}`}
                className={`milestone-timeline__tick${tick.isToday ? ' is-today' : ''}`}
                style={{ left: `${tick.leftPct}%` }}
                title={tick.isToday ? `오늘 (${tick.label})` : undefined}
              >
                <span className="milestone-timeline__tick-label">{tick.label}</span>
              </span>
            ))}
          </div>

          <div className="milestone-timeline__chart" ref={chartRef}>
            <span ref={measureRef} className="milestone-timeline__measure" aria-hidden="true" />
            <div className="milestone-timeline__grid" aria-hidden="true">
              {model.ticks.map((tick) => (
                <span
                  key={`grid-${tick.label}-${tick.leftPct}`}
                  className="milestone-timeline__grid-line"
                  style={{ left: `${tick.leftPct}%` }}
                />
              ))}
            </div>

            <div className="milestone-timeline__rows">
              {rowGroups.map((group) => {
                const isSelected = group.milestoneId === selectedId;
                return (
                  <div
                    key={group.milestoneId}
                    className="milestone-timeline__row"
                    ref={(el) => {
                      if (el) rowRefs.current.set(group.milestoneId, el);
                      else rowRefs.current.delete(group.milestoneId);
                    }}
                  >
                    {group.segments.map((row) => {
                      const isExpanded = expandedBar?.id === row.id;
                      return (
                        <button
                          key={row.id}
                          type="button"
                          className={`milestone-timeline__bar ${isSelected ? 'is-selected' : ''} ${isExpanded ? 'is-expanded' : ''}`}
                          style={
                            isExpanded
                              ? {
                                  left: `${expandedBar.leftPx}px`,
                                  width: `${expandedBar.widthPx}px`,
                                }
                              : {
                                  left: `${row.leftPct}%`,
                                  width: `${row.widthPct}%`,
                                }
                          }
                          aria-label={group.title}
                          title={group.title}
                          onMouseEnter={(e) => handleBarEnter({ ...row, title: group.title }, e)}
                          onMouseLeave={() => setExpandedBar(null)}
                          onClick={() => onSelect?.(group.milestoneId)}
                        >
                          <span className="milestone-timeline__bar-track" />
                          <span
                            className="milestone-timeline__bar-fill"
                            style={{ width: `${row.progress}%` }}
                          />
                          <span className="milestone-timeline__bar-label-wrap" aria-hidden="true">
                            <span
                              className="milestone-timeline__bar-label milestone-timeline__bar-label--fill"
                              style={{ clipPath: `inset(0 ${100 - row.progress}% 0 0)` }}
                            >
                              {group.title}
                            </span>
                            <span
                              className="milestone-timeline__bar-label milestone-timeline__bar-label--track"
                              style={{ clipPath: `inset(0 0 0 ${row.progress}%)` }}
                            >
                              {group.title}
                            </span>
                          </span>
                        </button>
                      );
                    })}
                  </div>
                );
              })}
            </div>
          </div>
        </div>
      )}
    </footer>
  );
}
