// TODO: remove Timeline components duplicates after deciding which to use in certain cases
// Timeline.tsx is now always virtualized and comes with a slider
// SimpleTimeline.tsx DOES NOT come with a slider and conditionally virtualized

'use client';

import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';

import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';

import CreationCard from '@/components/creations/CreationCard';
import { cn } from '@/lib/utils';
import { getCreationCardImageSrc, getCreationCardVideoId } from '@/utils/creationHelpers';
import { getColorConfig } from '@/utils/style';

import { CreationListItem } from '@/types/Creation';

function useWindowSize() {
  const [size, setSize] = useState<[number, number]>([0, 0]);

  useLayoutEffect(() => {
    function updateSize() {
      setSize([window.innerWidth, window.innerHeight]);
    }
    window.addEventListener('resize', updateSize);
    updateSize();
    return () => window.removeEventListener('resize', updateSize);
  }, []);
  return size;
}

interface TimelineProps {
  data: CreationListItem[];
  lineColor?: 'yellow' | 'cyan' | 'blue' | 'gray';
  hasSlider?: boolean;
  scrollToYear?: number;
  onVisibleYearChange?: (year: number) => void; // Report visible year back to parent
  showCreatorProfession?: boolean;
}

const Timeline: React.FC<TimelineProps> = ({
  data,
  lineColor,
  hasSlider,
  scrollToYear,
  onVisibleYearChange,
  showCreatorProfession,
}) => {
  const [width] = useWindowSize();
  const [columns, setColumns] = useState<number>(5);
  const containerRef = useRef<HTMLDivElement | null>(null);
  const virtuosoRef = useRef<VirtuosoHandle | null>(null);

  const getRowList = (data: CreationListItem[], columns: number) => {
    const chronological: CreationListItem[] = [];
    const nonChronological: CreationListItem[] = [];

    // Keep backend order (descending). Split into two groups by labelYear.
    for (let i = 0; i < (data?.length || 0); i++) {
      const item = data[i];
      const y = item?.labelYear;
      if (typeof y === 'number' && Number.isFinite(y)) {
        if (y === 1000) nonChronological.push(item);
        else chronological.push(item);
      }
    }

    const rows: CreationListItem[][] = [];
    const pushChunks = (arr: CreationListItem[]) => {
      let temp: CreationListItem[] = [];
      for (let i = 0; i < arr.length; i++) {
        temp.push(arr[i]);
        if (temp.length === columns) {
          rows.push(temp);
          temp = [];
        }
      }
      if (temp.length > 0) rows.push(temp);
    };

    // First chronological, then non-chronological blocks
    pushChunks(chronological);
    pushChunks(nonChronological);

    return rows;
  };

  useEffect(() => {
    let c = 1;
    if (width > 380) c = 2;
    if (width > 520) c = 3;
    if (width > 768) c = 4;
    if (width > 1024) c = 5;
    if (width > 1280) c = 6;
    if (width > 1500) c = 7;
    if (width > 1800) c = 8;
    setColumns(c);
  }, [width]);

  const rows = getRowList(data, columns);

  // Labels per row: for chronological rows label by year.
  // Special case: the last chronological row shows the oldest year in that row (rightmost item).
  const lastChronoRowIdx = (() => {
    let idx = -1;
    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];
      if (!row || row.length === 0) continue;
      const first = row[0];
      if (typeof first?.labelYear === 'number' && first.labelYear !== 1000) {
        idx = i; // keep updating until non-chron rows begin
      } else {
        break; // non-chronological blocks follow
      }
    }
    return idx;
  })();

  const yearLabels = rows.map((row, idx) => {
    if (!row || row.length === 0) return null;
    const first = row[0];
    if (typeof first?.labelYear !== 'number' || first.labelYear === 1000) {
      return null; // non-chron row
    }

    // If we're scrolling to a specific year and this row contains it, show that year
    if (scrollToYear && row.some((item) => item?.labelYear === scrollToYear)) {
      return String(scrollToYear);
    }

    if (idx === lastChronoRowIdx) {
      const last = row[row.length - 1];
      return typeof last?.labelYear === 'number' ? String(last.labelYear) : null;
    }
    return String(first.labelYear);
  });

  // Scroll to year when prop changes
  useEffect(() => {
    if (scrollToYear && rows.length > 0 && virtuosoRef.current) {
      const targetIndex = rows.findIndex((row: CreationListItem[]) => {
        if (!row || row.length === 0) return false;
        // Check if any item in the row has the target year
        return row.some((item) => item?.labelYear === scrollToYear);
      });

      if (targetIndex >= 0) {
        virtuosoRef.current?.scrollToIndex({
          index: targetIndex,
          align: 'start',
        });
      }
    }
  }, [scrollToYear, rows]);

  // Report visible year changes to parent
  const handleRangeChanged = useCallback(
    (range: { startIndex: number; endIndex: number }) => {
      if (onVisibleYearChange && rows.length > 0) {
        const firstVisibleRow = rows[range.startIndex];
        if (firstVisibleRow && firstVisibleRow.length > 0) {
          // Use the year label for this row (which respects scrollToYear)
          const rowYearLabel = yearLabels[range.startIndex];
          if (rowYearLabel) {
            const year = parseInt(rowYearLabel);
            if (!isNaN(year) && year !== 1000) {
              onVisibleYearChange(year);
            }
          }
        }
      }
    },
    [onVisibleYearChange, rows, yearLabels]
  );

  return (
    <div ref={containerRef} className="w-full">
      <div className="w-full flex">
        <div className="w-full flex flex-col">
          <Virtuoso
            ref={virtuosoRef}
            useWindowScroll
            totalCount={rows.length}
            rangeChanged={handleRangeChanged}
            itemContent={(index) => {
              const showYear = !!yearLabels[index];
              const thisYear = yearLabels[index];

              return (
                <Row
                  key={index}
                  data={rows[index]}
                  columns={columns}
                  showYear={showYear}
                  yearToShow={thisYear}
                  lineColor={lineColor}
                  hasSlider={hasSlider}
                  showCreatorProfession={showCreatorProfession}
                />
              );
            }}
          />
        </div>
      </div>
    </div>
  );
};

interface RowProps {
  data: CreationListItem[];
  columns: number;
  showYear: boolean;
  yearToShow: string | null;
  lineColor?: 'yellow' | 'cyan' | 'blue' | 'gray';
  hasSlider?: boolean;
  showCreatorProfession?: boolean;
}

const Row: React.FC<RowProps> = ({
  data,
  columns,
  showYear,
  yearToShow,
  lineColor,
  hasSlider,
  showCreatorProfession,
}) => {
  const hasImageOrVideo = (data: CreationListItem) => {
    return getCreationCardVideoId(data) || getCreationCardImageSrc(data) ? true : false;
  };

  const rowContainsImage = () => {
    for (let i = 0; i < data?.length; i++) if (hasImageOrVideo(data[i])) return true;
    return false;
  };

  // Non-chronological row: any item with labelYear === 1000
  const isNonChronologicalRow = () => {
    for (let i = 0; i < data?.length; i++) {
      const it = data[i];
      if (typeof it?.labelYear === 'number' && it.labelYear === 1000) {
        return true;
      }
    }
    return false;
  };

  return (
    <div className={cn('relative flex')}>
      <div className="flex-1 flex gap-2 py-4 overflow-hidden pr-2">
        {[...Array(columns)].map((_, index) =>
          data[index] ? (
            <CreationCard
              key={index}
              data={data[index]}
              rowContainsImage={rowContainsImage()}
              showCreatorProfession={showCreatorProfession}
              lifeTitleLines={16}
            />
          ) : (
            <div key={index} className="flex-1" />
          )
        )}
      </div>

      {/* Sentinel for slider-follow: center-anchored marker with the row's year */}
      {hasSlider && showYear && yearToShow && (
        <div
          className="az-year-sentinel"
          data-year={yearToShow}
          style={{
            position: 'absolute',
            left: 0,
            right: 0,
            top: '50%',
            height: 1,
            pointerEvents: 'none',
          }}
        />
      )}

      {/* Always keep the space, but only show the bar for chronological rows */}
      {!hasSlider && (
        <div
          className={
            'relative w-4 flex items-center justify-center overflow-hidden lg:overflow-visible ' +
            (!isNonChronologicalRow() && lineColor
              ? getColorConfig(lineColor).backgroundClassName
              : !isNonChronologicalRow()
                ? 'bg-mma-yellow'
                : 'bg-transparent')
          }
        >
          <div className="lg:w-0 lg:absolute right-0">
            {showYear && yearToShow && (
              <div className="font-slab font-bold text-mma-blue -rotate-90 lg:rotate-0 lg:pl-2">
                {yearToShow}
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
};

export default Timeline;
