import * as React from "react";
import { useCallback, useMemo } from "@wordpress/element";
import { SelectControl, __experimentalGrid as Grid } from "@wordpress/components";
import { __ } from "@wordpress/i18n";
import type { Title, TitleSelection, Season } from "../../types";
import { TitleInfo } from "../title-info/TitleInfo";
import { TitleSelect } from "../title-select/TitleSelect";
import { getId, getIdData } from "../../context/api";

export type TitleControlsProps<T extends TitleSelection, C extends React.ElementType = "div"> = {
  as?: C;
  inputRef?: React.RefObject<HTMLInputElement>;
  titleSelection?: T;
  onTitleSelectionChange?: (titleSelection: T) => void;
  highlight?: boolean;
}

export const TitleControls = <T extends TitleSelection, C extends React.ElementType = "div">({
  inputRef,
  titleSelection,
  onTitleSelectionChange,
  ...props
}: TitleControlsProps<T, C>): JSX.Element => {
  const idType = titleSelection?.idType;
  const selectedTitle = titleSelection ? {
    ...(titleSelection.id && { [`${idType}Id`]: titleSelection.id }),
    ...(titleSelection.meta as Title),
  } : undefined;

  // Handle title selection
  const handleTitleSelect = useCallback((title: Title) => {
    const id = getId(title, idType || "justwatch");
    const newTitleSelection = {
      ...titleSelection,
      id,
      objectType: title.objectType,
      meta: title,
    } as T;

    if (title.objectType === "show") {
      newTitleSelection.seasonNumber = 1;
      newTitleSelection.episodeNumber = 1;
    }

    onTitleSelectionChange?.(newTitleSelection);
  }, [onTitleSelectionChange, titleSelection?.idType]);

  const {
    selectedSeason,
    maxSeasonNumber,
    seasonOptions,
    episodeOptions,
  } = useMemo(() => {
    const seasonNumber = titleSelection?.seasonNumber;
    const episodeNumber = titleSelection?.episodeNumber;

    // Calculate seasons and episodes
    const selectedSeasonNumber = seasonNumber || 1;
    const maxSeasonNumber = selectedTitle?.seasons?.length || selectedTitle?.maxSeasonNumber || 1;
    const seasons = selectedTitle?.seasons ?? Array.from({ length: maxSeasonNumber }, (_, i) => ({
      seasonNumber: i + 1,
      maxEpisodeNumber: 1,
    }));

    const selectedSeason: Season | undefined = seasons.find((season: Season) => season.seasonNumber === selectedSeasonNumber);
    const maxEpisodeNumber = selectedSeason?.maxEpisodeNumber || 1;
    const seasonOptions = Array.from({ length: maxSeasonNumber }, (_, i) => ({
      label: `${__('Season', 'justwatch-partner-integrations')} ${i + 1}`,
      value: String(i + 1),
      selected: i + 1 === seasonNumber,
    }));

    const episodeOptions = Array.from({ length: maxEpisodeNumber }, (_, i) => ({
      label: `${__('Episode', 'justwatch-partner-integrations')} ${i + 1}`,
      value: String(i + 1),
      selected: i + 1 === episodeNumber,
    }));

    return {
      selectedSeason,
      maxSeasonNumber,
      seasonOptions,
      episodeOptions,
    };
  }, [titleSelection?.id, titleSelection?.objectType, titleSelection?.seasonNumber, selectedTitle]);

  const handleSeasonChange = (newSeasonNumber: string) => {
    onTitleSelectionChange?.({
      ...titleSelection,
      seasonNumber: Number(newSeasonNumber),
      episodeNumber: 1,
    } as T);
  };

  const handleEpisodeChange = (newEpisodeNumber: string) => {
    onTitleSelectionChange?.({
      ...titleSelection,
      episodeNumber: Number(newEpisodeNumber),
    } as T);
  };

  const handleTitleData = useCallback((title: Title) => {
    const id = getId(title, idType || "justwatch");

    if (titleSelection && titleSelection.id === id) {
      onTitleSelectionChange?.({
        ...titleSelection,
        meta: title,
      } as T);
    }
  }
  , [onTitleSelectionChange, titleSelection?.id]);

  const help = useMemo(() => {
    let content: React.ReactNode = null;

    if (!selectedTitle) {
      content = <span>Search for a title or id (imdb, justwatch, tmdb)</span>;
    } else {
      const idType = getIdData(selectedTitle, titleSelection?.id, titleSelection?.idType).idType;

      content = (
        <TitleInfo
          as="span"
          item={selectedTitle}
          idType={idType}
          details
        />
      );
    }

    return <span style={{ display: "block", marginBottom: 16 }}>{content}</span>;
  }, [titleSelection?.id, titleSelection?.objectType, titleSelection?.idType, selectedTitle]);

  return (
    <div {...props}>
      <TitleSelect
        label="Title"
        inputRef={inputRef}
        selectedTitle={selectedTitle}
        onTitleSelect={handleTitleSelect}
        help={help}
        idType={titleSelection?.idType}
        onTitleData={handleTitleData}
      />
      {titleSelection?.objectType && titleSelection.objectType === "show" && (
        <Grid>
          <SelectControl
            __next40pxDefaultSize
            label={__("Season", "justwatch-partner-integrations")}
            value={String(titleSelection.seasonNumber)}
            options={seasonOptions}
            onChange={(value) => handleSeasonChange(value)}
            help={selectedTitle ? `${maxSeasonNumber} seasons` : ""}
          />
          <SelectControl
            __next40pxDefaultSize
            label={__("Episode", "justwatch-partner-integrations")}
            value={String(titleSelection.episodeNumber)}
            options={episodeOptions}
            onChange={handleEpisodeChange}
            help={selectedSeason ? `${selectedSeason.maxEpisodeNumber} episodes` : ""}
          />
        </Grid>
      )}
    </div>
  );
};

export default TitleControls;