import { useMemo, useRef, useEffect, useCallback } from 'react';
import { Typography, theme } from 'antd';
import {
  BellOutlined,
  EnvironmentOutlined,
  LockOutlined,
} from '@ant-design/icons';
import dayjs from 'dayjs';
import type { PersonalCalendarItem } from '@/types/api';
import {
  hexToRgba,
  assignLanes,
  formatHourLabel,
  getViewDates,
  formatTimeShort,
  START_HOUR,
  END_HOUR,
  SLOT_HEIGHT,
} from './calendarUtils';

const { Text } = Typography;

interface CalendarTimeGridProps {
  items: PersonalCalendarItem[];
  viewMode: 'day' | '3day' | 'week';
  currentDate: dayjs.Dayjs;
  onDateSelect: (date: string) => void;
  onItemClick: (item: PersonalCalendarItem) => void;
  onNavigate: (direction: 'prev' | 'next') => void;
}

const GUTTER_WIDTH = 44;
const totalHeight = (END_HOUR - START_HOUR) * SLOT_HEIGHT;
const SWIPE_THRESHOLD = 50;

export default function CalendarTimeGrid({
  items,
  viewMode,
  currentDate,
  onDateSelect,
  onItemClick,
  onNavigate,
}: CalendarTimeGridProps) {
  const { token } = theme.useToken();
  const scrollRef = useRef<HTMLDivElement>(null);
  const touchStartRef = useRef<{ x: number; y: number } | null>(null);

  const dates = useMemo(() => getViewDates(viewMode, currentDate), [viewMode, currentDate]);
  const todayKey = dayjs().format('YYYY-MM-DD');

  // Scroll to current time on mount
  useEffect(() => {
    if (scrollRef.current) {
      const now = dayjs();
      const minutes = now.hour() * 60 + now.minute();
      const scrollTo = ((minutes - START_HOUR * 60) / 60) * SLOT_HEIGHT - 100;
      scrollRef.current.scrollTop = Math.max(0, scrollTo);
    }
  }, []);

  // Group items by date
  const itemsByDate = useMemo(() => {
    const map: Record<string, PersonalCalendarItem[]> = {};
    for (const item of items) {
      if (!map[item.date]) map[item.date] = [];
      map[item.date]!.push(item);
    }
    return map;
  }, [items]);

  // Touch swipe handling
  const handleTouchStart = useCallback((e: React.TouchEvent) => {
    const touch = e.touches[0];
    if (touch) {
      touchStartRef.current = { x: touch.clientX, y: touch.clientY };
    }
  }, []);

  const handleTouchEnd = useCallback((e: React.TouchEvent) => {
    if (!touchStartRef.current) return;
    const touch = e.changedTouches[0];
    if (!touch) return;
    const dx = touch.clientX - touchStartRef.current.x;
    const dy = touch.clientY - touchStartRef.current.y;
    touchStartRef.current = null;

    // Only trigger swipe if horizontal movement is dominant
    if (Math.abs(dx) > SWIPE_THRESHOLD && Math.abs(dx) > Math.abs(dy) * 1.5) {
      onNavigate(dx < 0 ? 'next' : 'prev');
    }
  }, [onNavigate]);

  // Current time indicator
  const nowIndicatorTop = useMemo(() => {
    const now = dayjs();
    const minutes = now.hour() * 60 + now.minute();
    const top = ((minutes - START_HOUR * 60) / 60) * SLOT_HEIGHT;
    if (top < 0 || top > totalHeight) return null;
    return top;
  }, []);

  const columnCount = dates.length;
  const isNarrow = viewMode === 'week';

  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        height: 'calc(100vh - 180px)',
        background: 'rgba(255,255,255,0.02)',
        borderRadius: 8,
        border: '1px solid rgba(255,255,255,0.08)',
        overflow: 'hidden',
      }}
      onTouchStart={handleTouchStart}
      onTouchEnd={handleTouchEnd}
    >
      {/* Column headers */}
      <div
        style={{
          display: 'flex',
          borderBottom: '1px solid rgba(255,255,255,0.08)',
          background: 'rgba(255,255,255,0.03)',
          flexShrink: 0,
        }}
      >
        {/* Gutter spacer */}
        <div style={{ width: GUTTER_WIDTH, flexShrink: 0 }} />

        {dates.map((date) => {
          const dateKey = date.format('YYYY-MM-DD');
          const isToday = dateKey === todayKey;

          return (
            <div
              key={dateKey}
              onClick={() => onDateSelect(dateKey)}
              style={{
                flex: 1,
                textAlign: 'center',
                padding: '8px 2px',
                cursor: 'pointer',
                borderLeft: '1px solid rgba(255,255,255,0.06)',
              }}
            >
              <Text
                style={{
                  fontSize: isNarrow ? 11 : 12,
                  color: 'rgba(255,255,255,0.45)',
                  display: 'block',
                  textTransform: 'uppercase',
                  letterSpacing: 0.5,
                }}
              >
                {isNarrow ? date.format('dd') : date.format('ddd')}
              </Text>
              <div
                style={{
                  display: 'inline-flex',
                  alignItems: 'center',
                  justifyContent: 'center',
                  width: isNarrow ? 24 : 28,
                  height: isNarrow ? 24 : 28,
                  borderRadius: '50%',
                  background: isToday ? token.colorPrimary : 'transparent',
                  color: isToday ? '#fff' : 'rgba(255,255,255,0.85)',
                  fontSize: isNarrow ? 13 : 15,
                  fontWeight: isToday ? 700 : 500,
                  marginTop: 2,
                }}
              >
                {date.format('D')}
              </div>
            </div>
          );
        })}
      </div>

      {/* All-day section */}
      <AllDaySection
        dates={dates}
        itemsByDate={itemsByDate}
        onItemClick={onItemClick}
        isNarrow={isNarrow}
      />

      {/* Scrollable time grid */}
      <div
        ref={scrollRef}
        style={{
          flex: 1,
          overflowY: 'auto',
          overflowX: 'hidden',
          position: 'relative',
        }}
      >
        <div style={{ position: 'relative', height: totalHeight }}>
          {/* Hour lines */}
          {Array.from({ length: END_HOUR - START_HOUR + 1 }, (_, i) => {
            const hour = START_HOUR + i;
            const top = i * SLOT_HEIGHT;
            return (
              <div
                key={hour}
                style={{
                  position: 'absolute',
                  top,
                  left: 0,
                  right: 0,
                  display: 'flex',
                  alignItems: 'flex-start',
                }}
              >
                <Text
                  style={{
                    width: GUTTER_WIDTH,
                    fontSize: 11,
                    color: 'rgba(255,255,255,0.3)',
                    textAlign: 'right',
                    paddingRight: 8,
                    marginTop: -7,
                    flexShrink: 0,
                  }}
                >
                  {formatHourLabel(hour)}
                </Text>
                <div
                  style={{
                    flex: 1,
                    borderTop: '1px solid rgba(255,255,255,0.06)',
                    height: 0,
                  }}
                />
              </div>
            );
          })}

          {/* Column dividers */}
          {dates.map((date, i) => {
            if (i === 0) return null;
            return (
              <div
                key={`div-${date.format('YYYY-MM-DD')}`}
                style={{
                  position: 'absolute',
                  top: 0,
                  bottom: 0,
                  left: `calc(${GUTTER_WIDTH}px + ${(i / columnCount) * 100}% * (1 - ${GUTTER_WIDTH}px / 100%))`,
                  width: 1,
                  background: 'rgba(255,255,255,0.06)',
                }}
              />
            );
          })}

          {/* Column click zones (for creating events on empty space) */}
          {dates.map((date, i) => {
            const dateKey = date.format('YYYY-MM-DD');
            return (
              <div
                key={`zone-${dateKey}`}
                onClick={() => onDateSelect(dateKey)}
                style={{
                  position: 'absolute',
                  top: 0,
                  bottom: 0,
                  left: `calc(${GUTTER_WIDTH}px + ${(i / columnCount)} * (100% - ${GUTTER_WIDTH}px))`,
                  width: `calc((100% - ${GUTTER_WIDTH}px) / ${columnCount})`,
                  cursor: 'pointer',
                }}
              />
            );
          })}

          {/* Current time indicator */}
          {nowIndicatorTop !== null && dates.some((d) => d.format('YYYY-MM-DD') === todayKey) && (
            <div
              style={{
                position: 'absolute',
                top: nowIndicatorTop,
                left: GUTTER_WIDTH,
                right: 0,
                height: 2,
                background: token.colorError,
                zIndex: 5,
                borderRadius: 1,
                pointerEvents: 'none',
              }}
            >
              <div
                style={{
                  position: 'absolute',
                  left: -4,
                  top: -3,
                  width: 8,
                  height: 8,
                  borderRadius: '50%',
                  background: token.colorError,
                }}
              />
            </div>
          )}

          {/* Events per column */}
          {dates.map((date, colIndex) => {
            const dateKey = date.format('YYYY-MM-DD');
            const dayItems = (itemsByDate[dateKey] ?? []).filter((it) => !it.isAllDay);
            const lanedItems = assignLanes(dayItems);

            return lanedItems.map(({ item, top, height, lane, totalLanes }) => {
              const colWidth = `calc((100% - ${GUTTER_WIDTH}px) / ${columnCount})`;
              const colLeft = `calc(${GUTTER_WIDTH}px + ${colIndex} * (100% - ${GUTTER_WIDTH}px) / ${columnCount})`;
              const laneWidth = totalLanes > 1 ? `calc(${100 / totalLanes}% - 2px)` : 'calc(100% - 6px)';
              const laneOffset = totalLanes > 1 ? `calc(${(lane / totalLanes) * 100}% + 1px)` : '3px';

              return (
                <EventBlock
                  key={item.id}
                  item={item}
                  top={top}
                  height={height}
                  colLeft={colLeft}
                  colWidth={colWidth}
                  laneWidth={laneWidth}
                  laneOffset={laneOffset}
                  isNarrow={isNarrow}
                  onClick={() => onItemClick(item)}
                />
              );
            });
          })}
        </div>
      </div>
    </div>
  );
}

/** All-day events section spanning across columns */
function AllDaySection({
  dates,
  itemsByDate,
  onItemClick,
  isNarrow,
}: {
  dates: dayjs.Dayjs[];
  itemsByDate: Record<string, PersonalCalendarItem[]>;
  onItemClick: (item: PersonalCalendarItem) => void;
  isNarrow: boolean;
}) {
  const hasAllDay = dates.some((d) => {
    const items = itemsByDate[d.format('YYYY-MM-DD')];
    return items?.some((it) => it.isAllDay);
  });

  if (!hasAllDay) return null;

  return (
    <div
      style={{
        display: 'flex',
        borderBottom: '1px solid rgba(255,255,255,0.08)',
        flexShrink: 0,
        minHeight: 28,
      }}
    >
      <div
        style={{
          width: GUTTER_WIDTH,
          flexShrink: 0,
          fontSize: 10,
          color: 'rgba(255,255,255,0.3)',
          textAlign: 'right',
          paddingRight: 8,
          paddingTop: 4,
        }}
      >
        all-day
      </div>
      {dates.map((date) => {
        const dateKey = date.format('YYYY-MM-DD');
        const allDay = (itemsByDate[dateKey] ?? []).filter((it) => it.isAllDay);
        return (
          <div
            key={dateKey}
            style={{
              flex: 1,
              borderLeft: '1px solid rgba(255,255,255,0.06)',
              padding: '2px 2px',
              display: 'flex',
              flexDirection: 'column',
              gap: 2,
            }}
          >
            {allDay.map((item) => (
              <div
                key={item.id}
                onClick={() => onItemClick(item)}
                style={{
                  background: hexToRgba(item.color, 0.2),
                  borderLeft: `3px solid ${item.color}`,
                  borderRadius: 4,
                  padding: '2px 4px',
                  fontSize: isNarrow ? 10 : 11,
                  color: 'rgba(255,255,255,0.85)',
                  cursor: 'pointer',
                  overflow: 'hidden',
                  whiteSpace: 'nowrap',
                  textOverflow: 'ellipsis',
                }}
              >
                {item.title}
              </div>
            ))}
          </div>
        );
      })}
    </div>
  );
}

/** Individual event block positioned within a column */
function EventBlock({
  item,
  top,
  height,
  colLeft,
  colWidth,
  laneWidth,
  laneOffset,
  isNarrow,
  onClick,
}: {
  item: PersonalCalendarItem;
  top: number;
  height: number;
  colLeft: string;
  colWidth: string;
  laneWidth: string;
  laneOffset: string;
  isNarrow: boolean;
  onClick: () => void;
}) {
  const { token } = theme.useToken();
  const isTimeBlock = item.itemType === 'TIME_BLOCK';
  const isReminder = item.itemType === 'REMINDER';
  const color = item.color || token.colorPrimary;
  const isBusyHidden = isTimeBlock && item.showDetailsTo === 'NOBODY';

  return (
    <div
      onClick={(e) => {
        e.stopPropagation();
        onClick();
      }}
      style={{
        position: 'absolute',
        top: top + 1,
        left: `calc(${colLeft} + ${laneOffset})`,
        width: `calc(min(${colWidth}, ${laneWidth}))`,
        height: height - 2,
        background: isTimeBlock ? hexToRgba(color, 0.1) : hexToRgba(color, 0.2),
        border: isTimeBlock
          ? `1px dashed ${hexToRgba(color, 0.35)}`
          : `1px solid ${hexToRgba(color, 0.4)}`,
        borderLeft: `3px solid ${color}`,
        borderRadius: 6,
        padding: isNarrow ? '2px 3px' : '4px 8px',
        cursor: 'pointer',
        overflow: 'hidden',
        zIndex: 2,
        transition: 'background 0.15s',
      }}
    >
      {isBusyHidden ? (
        <Text style={{ fontSize: isNarrow ? 10 : 12, color: 'rgba(255,255,255,0.45)' }}>
          <LockOutlined style={{ marginRight: 4, fontSize: 10 }} />
          {!isNarrow && 'Busy'}
        </Text>
      ) : (
        <>
          <Text
            strong
            style={{
              fontSize: isNarrow ? 10 : 12,
              color: 'rgba(255,255,255,0.85)',
              display: 'block',
              overflow: 'hidden',
              textOverflow: 'ellipsis',
              whiteSpace: 'nowrap',
            }}
          >
            {isReminder && <BellOutlined style={{ marginRight: 3, fontSize: 10 }} />}
            {item.title}
          </Text>
          {!isNarrow && (
            <Text style={{ fontSize: 11, color: 'rgba(255,255,255,0.5)' }}>
              {formatTimeShort(item.startTime)} - {formatTimeShort(item.endTime)}
            </Text>
          )}
          {isNarrow && height > 30 && (
            <Text style={{ fontSize: 9, color: 'rgba(255,255,255,0.45)', display: 'block' }}>
              {formatTimeShort(item.startTime)}
            </Text>
          )}
          {item.location && height > 45 && !isNarrow && (
            <Text
              style={{
                fontSize: 10,
                color: 'rgba(255,255,255,0.4)',
                display: 'block',
                overflow: 'hidden',
                textOverflow: 'ellipsis',
                whiteSpace: 'nowrap',
              }}
            >
              <EnvironmentOutlined style={{ marginRight: 3 }} />
              {item.location}
            </Text>
          )}
        </>
      )}
    </div>
  );
}
