import { useState, useCallback, useRef, useEffect } from 'react';
import { batchApi, type ExecutionInfo, type JobExecutionDto, type PeriodInfo, type ScheduleTimeline } from '../api/batchApi';
import { formatDateTime, calculateDuration } from '../utils/formatters';
import { usePoller } from '../hooks/usePoller';
import { useToastContext } from '../contexts/ToastContext';
import { getStatusColor } from '../components/StatusBadge';
import StatusBadge from '../components/StatusBadge';
import LoadingSpinner from '../components/LoadingSpinner';
import EmptyState from '../components/EmptyState';

type ViewType = 'day' | 'week' | 'month';

interface TooltipData {
  jobName: string;
  period: PeriodInfo;
  execution: ExecutionInfo;
  x: number;
  y: number;
}

interface SelectedCell {
  jobName: string;
  periodKey: string;
  periodLabel: string;
}

const VIEW_OPTIONS: { value: ViewType; label: string }[] = [
  { value: 'day', label: 'Day' },
  { value: 'week', label: 'Week' },
  { value: 'month', label: 'Month' },
];

const LEGEND_ITEMS = [
  { status: 'COMPLETED', color: '#10b981', label: '완료' },
  { status: 'FAILED', color: '#ef4444', label: '실패' },
  { status: 'STARTED', color: '#3b82f6', label: '실행중' },
  { status: 'SCHEDULED', color: '#8b5cf6', label: '예정' },
  { status: 'NONE', color: '#e5e7eb', label: '없음' },
];

const JOB_COL_WIDTH = 200;
const CELL_MIN_WIDTH = 80;
const POLLING_INTERVAL = 30000;

function formatDateStr(date: Date): string {
  const y = date.getFullYear();
  const m = String(date.getMonth() + 1).padStart(2, '0');
  const d = String(date.getDate()).padStart(2, '0');
  return `${y}-${m}-${d}`;
}

function shiftDate(date: Date, view: ViewType, delta: number): Date {
  const next = new Date(date);
  switch (view) {
    case 'day':
      next.setDate(next.getDate() + delta);
      break;
    case 'week':
      next.setDate(next.getDate() + delta * 7);
      break;
    case 'month':
      next.setMonth(next.getMonth() + delta);
      break;
  }
  return next;
}

function isRunning(status: string): boolean {
  return status === 'STARTED' || status === 'STARTING';
}

export default function Timeline() {
  const { showToast } = useToastContext();

  const [view, setView] = useState<ViewType>('day');
  const [currentDate, setCurrentDate] = useState(() => new Date());
  const [periodLabel, setPeriodLabel] = useState('');
  const [periods, setPeriods] = useState<PeriodInfo[]>([]);
  const [schedules, setSchedules] = useState<ScheduleTimeline[]>([]);
  const [loading, setLoading] = useState(true);

  // Tooltip
  const [tooltip, setTooltip] = useState<TooltipData | null>(null);
  const tooltipTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  // Selected cell & detail panel
  const [selectedCell, setSelectedCell] = useState<SelectedCell | null>(null);
  const [detailExecutions, setDetailExecutions] = useState<JobExecutionDto[]>([]);
  const [detailLoading, setDetailLoading] = useState(false);

  const loadTimeline = useCallback(async () => {
    try {
      const dateStr = formatDateStr(currentDate);
      const result = await batchApi.getTimeline(view, dateStr);
      setPeriodLabel(result.periodLabel);
      setPeriods(result.periods);
      setSchedules(result.schedules);
    } catch (err) {
      showToast('타임라인 조회 실패', 'error');
      console.error(err);
    } finally {
      setLoading(false);
    }
  }, [view, currentDate, showToast]);

  usePoller(loadTimeline, POLLING_INTERVAL, [view, currentDate]);

  const handlePrev = () => setCurrentDate((d) => shiftDate(d, view, -1));
  const handleNext = () => setCurrentDate((d) => shiftDate(d, view, 1));
  const handleToday = () => setCurrentDate(new Date());

  const handleRefresh = async () => {
    setLoading(true);
    await loadTimeline();
  };

  // Tooltip handlers
  const handleCellMouseEnter = (
    e: React.MouseEvent,
    jobName: string,
    period: PeriodInfo,
    execution: ExecutionInfo,
  ) => {
    if (tooltipTimeoutRef.current) {
      clearTimeout(tooltipTimeoutRef.current);
    }
    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
    setTooltip({
      jobName,
      period,
      execution,
      x: rect.left + rect.width / 2,
      y: rect.top,
    });
  };

  const handleCellMouseLeave = () => {
    tooltipTimeoutRef.current = setTimeout(() => {
      setTooltip(null);
    }, 100);
  };

  // Clean up tooltip timeout
  useEffect(() => {
    return () => {
      if (tooltipTimeoutRef.current) {
        clearTimeout(tooltipTimeoutRef.current);
      }
    };
  }, []);

  // Cell click -> detail panel
  const handleCellClick = async (jobName: string, periodKey: string, periodLabel: string) => {
    // Toggle off if clicking same cell
    if (selectedCell?.jobName === jobName && selectedCell?.periodKey === periodKey) {
      setSelectedCell(null);
      setDetailExecutions([]);
      return;
    }

    setSelectedCell({ jobName, periodKey, periodLabel });
    setDetailLoading(true);
    setDetailExecutions([]);

    try {
      const executions = await batchApi.getPeriodExecutions(jobName, view, periodKey);
      setDetailExecutions(executions);
    } catch (err) {
      showToast('구간 실행 이력 조회 실패', 'error');
      console.error(err);
    } finally {
      setDetailLoading(false);
    }
  };

  const closeDetail = () => {
    setSelectedCell(null);
    setDetailExecutions([]);
  };

  const gridTemplateColumns = `${JOB_COL_WIDTH}px repeat(${periods.length}, minmax(${CELL_MIN_WIDTH}px, 1fr))`;

  return (
    <div className="space-y-4">
      {/* Controls */}
      <div className="bg-wing-surface rounded-xl shadow-lg p-4">
        <div className="flex flex-wrap items-center gap-3">
          {/* View Toggle */}
          <div className="flex rounded-lg border border-wing-border overflow-hidden">
            {VIEW_OPTIONS.map((opt) => (
              <button
                key={opt.value}
                onClick={() => {
                  setView(opt.value);
                  setLoading(true);
                }}
                className={`px-4 py-1.5 text-sm font-medium transition-colors ${
                  view === opt.value
                    ? 'bg-wing-accent text-white'
                    : 'bg-wing-surface text-wing-muted hover:bg-wing-accent/10'
                }`}
              >
                {opt.label}
              </button>
            ))}
          </div>

          {/* Navigation */}
          <div className="flex items-center gap-1">
            <button
              onClick={handlePrev}
              className="px-3 py-1.5 text-sm text-wing-muted bg-wing-card rounded-lg hover:bg-wing-hover transition-colors"
            >
              &larr; 이전
            </button>
            <button
              onClick={handleToday}
              className="px-3 py-1.5 text-sm font-medium text-wing-accent bg-wing-accent/10 rounded-lg hover:bg-wing-accent/15 transition-colors"
            >
              오늘
            </button>
            <button
              onClick={handleNext}
              className="px-3 py-1.5 text-sm text-wing-muted bg-wing-card rounded-lg hover:bg-wing-hover transition-colors"
            >
              다음 &rarr;
            </button>
          </div>

          {/* Period Label */}
          <span className="text-sm font-semibold text-wing-text">
            {periodLabel}
          </span>

          {/* Refresh */}
          <button
            onClick={handleRefresh}
            className="ml-auto px-3 py-1.5 text-sm text-wing-muted bg-wing-card rounded-lg hover:bg-wing-hover transition-colors"
          >
            새로고침
          </button>
        </div>
      </div>

      {/* Legend */}
      <div className="flex flex-wrap items-center gap-4 px-2">
        {LEGEND_ITEMS.map((item) => (
          <div key={item.status} className="flex items-center gap-1.5">
            <div
              className="w-4 h-4 rounded"
              style={{ backgroundColor: item.color }}
            />
            <span className="text-xs text-wing-muted">{item.label}</span>
          </div>
        ))}
      </div>

      {/* Timeline Grid */}
      <div className="bg-wing-surface rounded-xl shadow-lg overflow-hidden">
        {loading ? (
          <LoadingSpinner />
        ) : schedules.length === 0 ? (
          <EmptyState message="타임라인 데이터가 없습니다" sub="등록된 스케줄이 없거나 해당 기간에 실행 이력이 없습니다" />
        ) : (
          <div className="overflow-x-auto">
            <div
              className="grid min-w-max"
              style={{ gridTemplateColumns }}
            >
              {/* Header Row */}
              <div className="sticky left-0 z-20 bg-wing-card border-b border-r border-wing-border px-3 py-2 text-xs font-semibold text-wing-muted">
                작업명
              </div>
              {periods.map((period) => (
                <div
                  key={period.key}
                  className="bg-wing-card border-b border-r border-wing-border px-2 py-2 text-xs font-medium text-wing-muted text-center whitespace-nowrap"
                >
                  {period.label}
                </div>
              ))}

              {/* Data Rows */}
              {schedules.map((schedule) => (
                <>
                  {/* Job Name (sticky) */}
                  <div
                    key={`name-${schedule.jobName}`}
                    className="sticky left-0 z-10 bg-wing-surface border-b border-r border-wing-border px-3 py-2 text-xs font-medium text-wing-text truncate flex items-center"
                    title={schedule.jobName}
                  >
                    {schedule.jobName}
                  </div>

                  {/* Execution Cells */}
                  {periods.map((period) => {
                    const exec = schedule.executions[period.key];
                    const hasExec = exec !== null && exec !== undefined;
                    const isSelected =
                      selectedCell?.jobName === schedule.jobName &&
                      selectedCell?.periodKey === period.key;
                    const running = hasExec && isRunning(exec.status);

                    return (
                      <div
                        key={`cell-${schedule.jobName}-${period.key}`}
                        className={`border-b border-r border-wing-border/50 p-1 cursor-pointer transition-all hover:opacity-80 ${
                          isSelected ? 'ring-2 ring-yellow-400 ring-inset' : ''
                        }`}
                        onClick={() =>
                          handleCellClick(schedule.jobName, period.key, period.label)
                        }
                        onMouseEnter={
                          hasExec
                            ? (e) => handleCellMouseEnter(e, schedule.jobName, period, exec)
                            : undefined
                        }
                        onMouseLeave={hasExec ? handleCellMouseLeave : undefined}
                      >
                        {hasExec && (
                          <div
                            className={`w-full h-6 rounded ${running ? 'animate-pulse' : ''}`}
                            style={{ backgroundColor: getStatusColor(exec.status) }}
                          />
                        )}
                      </div>
                    );
                  })}
                </>
              ))}
            </div>
          </div>
        )}
      </div>

      {/* Tooltip */}
      {tooltip && (
        <div
          className="fixed z-50 pointer-events-none"
          style={{
            left: tooltip.x,
            top: tooltip.y - 8,
            transform: 'translate(-50%, -100%)',
          }}
        >
          <div className="bg-gray-900 text-white text-xs rounded-lg px-3 py-2 shadow-lg max-w-xs">
            <div className="font-semibold mb-1">{tooltip.jobName}</div>
            <div className="space-y-0.5 text-gray-300">
              <div>기간: {tooltip.period.label}</div>
              <div>
                상태:{' '}
                <span
                  className="font-medium"
                  style={{ color: getStatusColor(tooltip.execution.status) }}
                >
                  {tooltip.execution.status}
                </span>
              </div>
              {tooltip.execution.startTime && (
                <div>시작: {formatDateTime(tooltip.execution.startTime)}</div>
              )}
              {tooltip.execution.endTime && (
                <div>종료: {formatDateTime(tooltip.execution.endTime)}</div>
              )}
              {tooltip.execution.executionId && (
                <div>실행 ID: {tooltip.execution.executionId}</div>
              )}
            </div>
            {/* Arrow */}
            <div className="absolute left-1/2 -translate-x-1/2 top-full w-0 h-0 border-l-[6px] border-l-transparent border-r-[6px] border-r-transparent border-t-[6px] border-t-gray-900" />
          </div>
        </div>
      )}

      {/* Detail Panel */}
      {selectedCell && (
        <div className="bg-wing-surface rounded-xl shadow-lg p-6">
          <div className="flex items-center justify-between mb-4">
            <div>
              <h3 className="text-sm font-bold text-wing-text">
                {selectedCell.jobName}
              </h3>
              <p className="text-xs text-wing-muted mt-0.5">
                구간: {selectedCell.periodLabel}
              </p>
            </div>
            <button
              onClick={closeDetail}
              className="px-3 py-1.5 text-xs text-wing-muted bg-wing-card rounded-lg hover:bg-wing-hover transition-colors"
            >
              닫기
            </button>
          </div>

          {detailLoading ? (
            <LoadingSpinner className="py-6" />
          ) : detailExecutions.length === 0 ? (
            <EmptyState
              message="해당 구간에 실행 이력이 없습니다"
              icon="📭"
            />
          ) : (
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="border-b border-wing-border">
                    <th className="text-left py-2 px-3 text-xs font-semibold text-wing-muted">
                      실행 ID
                    </th>
                    <th className="text-left py-2 px-3 text-xs font-semibold text-wing-muted">
                      상태
                    </th>
                    <th className="text-left py-2 px-3 text-xs font-semibold text-wing-muted">
                      시작 시간
                    </th>
                    <th className="text-left py-2 px-3 text-xs font-semibold text-wing-muted">
                      종료 시간
                    </th>
                    <th className="text-left py-2 px-3 text-xs font-semibold text-wing-muted">
                      소요 시간
                    </th>
                    <th className="text-right py-2 px-3 text-xs font-semibold text-wing-muted">
                      상세
                    </th>
                  </tr>
                </thead>
                <tbody>
                  {detailExecutions.map((exec) => (
                    <tr
                      key={exec.executionId}
                      className="border-b border-wing-border/50 hover:bg-wing-hover"
                    >
                      <td className="py-2 px-3 text-xs font-mono text-wing-text">
                        #{exec.executionId}
                      </td>
                      <td className="py-2 px-3">
                        <StatusBadge status={exec.status} />
                      </td>
                      <td className="py-2 px-3 text-xs text-wing-muted">
                        {formatDateTime(exec.startTime)}
                      </td>
                      <td className="py-2 px-3 text-xs text-wing-muted">
                        {formatDateTime(exec.endTime)}
                      </td>
                      <td className="py-2 px-3 text-xs text-wing-muted">
                        {calculateDuration(exec.startTime, exec.endTime)}
                      </td>
                      <td className="py-2 px-3 text-right">
                        <a
                          href={`/executions/${exec.executionId}`}
                          className="text-xs text-wing-accent hover:text-wing-accent font-medium"
                        >
                          상세
                        </a>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      )}
    </div>
  );
}
