import { useQuery } from '@tanstack/react-query';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';

import { useContextSelector } from '@/hooks/useContextSelector';
import { ChevronDownIcon, ChevronRightIcon } from '@/icons';
import { useApiClient } from '@/lib/apiClient';

import StudioContext from './StudioContext';
import { StudioProjectManagementContext } from './StudioProjectManagementContext';

interface StudioVersionsTimelineProps {
  selectedDate: string; // ISO date string like "2025-01-15"
  onPreviewVersion?: (versionId: string, state: any) => void;
  onRestoreVersion?: (versionId: string, state: any) => void;
}

export default function StudioVersionsTimeline({
  selectedDate,
  onPreviewVersion,
  onRestoreVersion: _onRestoreVersion,
}: StudioVersionsTimelineProps) {
  const [expandedHours, setExpandedHours] = useState<Set<string>>(new Set());
  const [selectedVersionId, setSelectedVersionId] = useState<string | null>(
    null
  );
  const apiClient = useApiClient();

  const projectId = useContextSelector(
    StudioProjectManagementContext,
    (context) => context.loadedProject?.id
  );

  // Calculate timestamps for the selected date
  const dateTimestamps = useMemo(() => {
    const date = new Date(selectedDate);
    const from = new Date(
      Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0)
    ); // Start of day in UTC

    const to = new Date(
      Date.UTC(
        date.getFullYear(),
        date.getMonth(),
        date.getDate() + 1,
        0,
        0,
        0,
        0
      )
    ); // Start of next day in UTC

    return {
      fromTimestamp: from.toISOString(),
      toTimestamp: to.toISOString(),
    };
  }, [selectedDate]);

  // Fetch detailed version data for the date
  const { data: versionsData, isLoading } = useQuery({
    queryKey: ['studio-versions-detail', projectId, selectedDate],
    queryFn: async () => {
      const response = await apiClient.GET(
        '/api/studio/{project_id}/versions',
        {
          params: {
            path: { project_id: projectId! },
            query: {
              return_days_only: false,
              from_timestamp: dateTimestamps.fromTimestamp,
              to_timestamp: dateTimestamps.toTimestamp,
            },
          },
        }
      );
      return response.data;
    },
    enabled: !!projectId && !!selectedDate,
    staleTime: 0,
    refetchOnMount: true,
    refetchOnWindowFocus: false,
  });

  // Fetch version state when a version is selected
  const { data: versionState, isLoading: isLoadingVersionState } = useQuery({
    queryKey: ['studio-version-state', projectId, selectedVersionId],
    queryFn: async () => {
      if (!selectedVersionId) return null;
      const response = await apiClient.GET(
        '/api/studio/{project_id}/version/{version_id}',
        {
          params: {
            path: { project_id: projectId!, version_id: selectedVersionId },
          },
        }
      );
      return response.data;
    },
    enabled: !!projectId && !!selectedVersionId,
    staleTime: 30000, // Cache for 30 seconds since version states don't change
  });

  const lastLoadedVersionId = useRef<string | null>(null);

  // Handle version preview when state is fetched
  useEffect(() => {
    if (
      versionState?.state &&
      selectedVersionId &&
      onPreviewVersion &&
      versionState.id !== lastLoadedVersionId.current
    ) {
      lastLoadedVersionId.current = versionState.id;
      onPreviewVersion(selectedVersionId, versionState.state);
    }
  }, [versionState, selectedVersionId, onPreviewVersion]);

  // Auto-expand latest hour when version data changes
  useEffect(() => {
    if (
      versionsData?.aggregated_versions &&
      versionsData.aggregated_versions.length > 0
    ) {
      // Sort by latest first and auto-expand the latest hour
      const sortedHours = [...versionsData.aggregated_versions].sort(
        (a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime()
      );
      const latestHour = sortedHours[0].hour;
      setExpandedHours(new Set([latestHour]));
    }
  }, [versionsData?.aggregated_versions]);

  const toggleHourExpanded = useCallback((hour: string) => {
    setExpandedHours((prev) => {
      const newSet = new Set(prev);
      if (newSet.has(hour)) {
        newSet.delete(hour);
      } else {
        newSet.add(hour);
      }
      return newSet;
    });
  }, []);

  const previewPackageId = useContextSelector(
    StudioContext,
    (context) => context.previewController.previewPackage?.id
  );

  if (isLoading) {
    return (
      <div className='text-sm text-foreground-secondary'>
        Loading versions...
      </div>
    );
  }

  if (
    !versionsData?.aggregated_versions ||
    versionsData.aggregated_versions.length === 0
  ) {
    return (
      <div className='text-sm text-foreground-secondary'>
        No versions found for this date
      </div>
    );
  }

  return (
    <div className='relative'>
      {/* Vertical timeline line */}
      <div className='absolute top-0 bottom-0 left-3 z-5 w-px bg-border-primary'></div>

      <div className='space-y-0'>
        {versionsData.aggregated_versions
          .sort(
            (a, b) => new Date(b.hour).getTime() - new Date(a.hour).getTime()
          )
          .map((hourGroup) => {
            const isExpanded = expandedHours.has(hourGroup.hour);
            const sortedVersions = [...hourGroup.versions].sort(
              (a, b) =>
                new Date(b.created_at).getTime() -
                new Date(a.created_at).getTime()
            );

            return (
              <div key={hourGroup.hour}>
                {/* Hour header with timeline bullet */}
                <div className='relative'>
                  <button
                    onClick={() => toggleHourExpanded(hourGroup.hour)}
                    className='flex w-full items-center justify-between bg-background-secondary py-3 pr-4 pl-8 text-left transition-colors hover:bg-background-tertiary'
                  >
                    <div
                      className={`text-sm tabular-nums ${isExpanded ? 'text-foreground-primary' : 'text-foreground-secondary opacity-70'}`}
                    >
                      {new Date(hourGroup.hour).toLocaleTimeString([], {
                        hour: '2-digit',
                        minute: '2-digit',
                        hour12: true,
                      })}
                    </div>
                    {isExpanded ? (
                      <ChevronDownIcon className='h-4 w-4 text-foreground-secondary' />
                    ) : (
                      <ChevronRightIcon className='h-4 w-4 text-foreground-secondary' />
                    )}
                  </button>
                  <div
                    className={`absolute top-1/2 left-2 z-10 h-2 w-2 -translate-y-1/2 rounded-full ${isExpanded ? 'bg-foreground-primary' : 'bg-foreground-secondary opacity-50'}`}
                  ></div>
                </div>

                {/* Expanded versions */}
                {isExpanded && (
                  <div className='space-y-0 pb-2'>
                    {sortedVersions.map((version) => {
                      const isSelected =
                        selectedVersionId === version.version_id &&
                        previewPackageId === version.version_id;
                      return (
                        <div key={version.version_id} className='relative'>
                          <button
                            onClick={() =>
                              setSelectedVersionId(version.version_id)
                            }
                            disabled={
                              isLoadingVersionState &&
                              selectedVersionId === version.version_id
                            }
                            className='w-full py-1.5 pr-4 pl-8 text-left transition-colors hover:bg-background-secondary disabled:opacity-50'
                          >
                            <div
                              className={`text-sm tabular-nums ${isSelected ? 'text-foreground-primary' : 'text-foreground-secondary opacity-70'}`}
                            >
                              {new Date(version.created_at).toLocaleTimeString(
                                [],
                                {
                                  hour: '2-digit',
                                  minute: '2-digit',
                                  second: '2-digit',
                                  hour12: true,
                                }
                              )}
                            </div>
                          </button>
                          <div
                            className={`absolute top-1/2 left-2 z-10 h-2 w-2 -translate-y-1/2 rounded-full ${isSelected ? 'bg-foreground-primary' : 'bg-foreground-secondary opacity-50'}`}
                          ></div>
                        </div>
                      );
                    })}
                  </div>
                )}
              </div>
            );
          })}
      </div>
    </div>
  );
}
