import { useStatsigClient } from '@statsig/react-bindings';
import { useCallback, useState } from 'react';

import { useContextSelector } from '@/hooks/useContextSelector';
import { CreateIcon, ExtendRightIcon, SectionIcon } from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';

import Button, {
  Props as ButtonProps,
  ButtonShape,
  ButtonVariant,
} from '../button/Button';
import SpinnerSVG from '../svg/SpinnerSVG';
import { Tooltip, TooltipProps } from '../tooltip/Tooltip';
import StudioContext from './StudioContext';
import assignMetadata from './actions/assignMetadata';
import getExtendFromBeats from './apiWrappers/getExtendFromBeats';
import {
  getSelectionEndBeats,
  getSelectionEndSeconds,
  getSelectionStartBeats,
  getSelectionStartSeconds,
} from './selectors';
import useGenerateAndInsertV2 from './useGenerateAndInsertV2';

const buttonConfigs = {
  replace: {
    label: 'Replace',
    regenerateLabel: 'Regenerate',
    tooltip: 'Replace Section',
    regenerateTooltip: 'Regenerate Replaced Section',
    IconComponent: SectionIcon,
  },
  create: {
    label: 'Create',
    regenerateLabel: 'Regenerate',
    tooltip: 'Create Section',
    regenerateTooltip: 'Regenerate Created Section',
    IconComponent: CreateIcon,
  },
  extend: {
    label: 'Extend',
    regenerateLabel: 'Re-Extend',
    tooltip: 'Extend',
    regenerateTooltip: 'Regenerate Extension',
    IconComponent: ExtendRightIcon,
  },
};

export default function StudioGenerateButton({
  iconOnly = false,
  tooltipPlacement = 'left',
  className,
  eventTrigger,
  ...otherProps
}: {
  iconOnly?: boolean;
  tooltipPlacement?: TooltipProps['placement'];
  className?: string;
  eventTrigger: 'sidebar' | 'selection-interactions';
} & ButtonProps) {
  const previewController = useContextSelector(
    StudioContext,
    (context) => context.previewController
  );
  const generateMode = useContextSelector(
    StudioContext,
    (context) => context.generateMode
  );
  const setState = useContextSelector(
    StudioContext,
    (context) => context.setState
  );
  const editSessionId = useContextSelector(
    StudioContext,
    (context) => context.editSessionId
  );
  const showContextWindow = useContextSelector(
    StudioContext,
    (context) => context.showContextWindow
  );
  const contextBeatsSetting = useContextSelector(
    StudioContext,
    (context) => context.contextBeatsSetting
  );
  const replaceMode = useContextSelector(
    StudioContext,
    (context) => context.replaceMode
  );
  const regenerateParams = useContextSelector(
    StudioContext,
    (context) => context.regenerateParams
  );
  const lyricsEditController = useContextSelector(
    StudioContext,
    (context) => context.lyricsEditController
  );
  const editClipId = useContextSelector(
    StudioContext,
    (context) => context.state.editClipId
  );
  const selectionStartBeats = useContextSelector(StudioContext, (context) =>
    getSelectionStartBeats(context.state)
  );
  const selectionStartSeconds = useContextSelector(StudioContext, (context) =>
    getSelectionStartSeconds(context.state)
  );
  const selectionEndBeats = useContextSelector(StudioContext, (context) =>
    getSelectionEndBeats(context.state)
  );
  const selectionEndSeconds = useContextSelector(StudioContext, (context) =>
    getSelectionEndSeconds(context.state)
  );
  const generateBlockingErrorMessage = useContextSelector(
    StudioContext,
    (context) => context.generateBlockingErrorMessage
  );
  const extendFromBeats = useContextSelector(StudioContext, (context) =>
    getExtendFromBeats(context.state)
  );

  const { generateInPlace, generateExtension } = useGenerateAndInsertV2();
  const [startingGeneration, setStartingGeneration] = useState(false);
  const statsigClient = useStatsigClient();

  const handleClick = useCallback(() => {
    previewController.stopPreviewing();
    if (generateMode === 'create') {
      setStartingGeneration(true);
      generateInPlace('infill').finally(() => {
        setTimeout(() => setStartingGeneration(false), 250);
      });
      setState(assignMetadata({ usedCreateSection: true }));
      logWebUserEvent({
        actionName: 'EditV3CreateSectionSubmitted',
        context: {
          editSessionId: editSessionId,
          editingClipId: editClipId || 'MISSING_EDIT_CLIP_ID',
          startBeats: selectionStartBeats,
          startSeconds: selectionStartSeconds,
          endBeats: selectionEndBeats,
          endSeconds: selectionEndSeconds,
          editedLyrics: lyricsEditController.editedLyrics !== null,
          contextWindowOverride: showContextWindow
            ? contextBeatsSetting
            : undefined,
          trigger: eventTrigger,
        },
      });
    } else if (generateMode === 'replace') {
      setStartingGeneration(true);
      generateInPlace(replaceMode).finally(() => {
        setTimeout(() => setStartingGeneration(false), 250);
      });
      setState(assignMetadata({ usedReplaceSection: true }));
      logWebUserEvent({
        actionName: 'EditV3ReplaceSectionSubmitted',
        context: {
          editSessionId: editSessionId,
          editingClipId: editClipId || 'MISSING_EDIT_CLIP_ID',
          startBeats: selectionStartBeats,
          startSeconds: selectionStartSeconds,
          endBeats: selectionEndBeats,
          endSeconds: selectionEndSeconds,
          mode: {
            fixed_infill: 'fixed' as const,
            smart_infill: 'smart' as const,
            infill: 'classic' as const,
          }[replaceMode],
          isRegenerate: !!regenerateParams,
          editedLyrics: lyricsEditController.editedLyrics !== null,
          contextWindowOverride: showContextWindow
            ? contextBeatsSetting
            : undefined,
          trigger: eventTrigger,
        },
      });
    } else if (generateMode === 'extend') {
      setStartingGeneration(true);
      generateExtension(extendFromBeats).finally(() => {
        setTimeout(() => setStartingGeneration(false), 250);
      });
      logWebUserEvent({
        actionName: 'EditV3ExtendSubmitted',
        context: {
          editSessionId: editSessionId,
          editingClipId: editClipId || 'MISSING_EDIT_CLIP_ID',
          fromBeats: selectionStartBeats,
          fromSeconds: selectionStartSeconds,
          isRegenerate: !!regenerateParams,
          editedLyrics: lyricsEditController.editedLyrics !== null,
          trigger: eventTrigger,
        },
      });
      setState(assignMetadata({ usedExtend: true }));
    }
  }, [
    generateInPlace,
    generateExtension,
    generateMode,
    editClipId,
    regenerateParams,
    selectionStartBeats,
    selectionStartSeconds,
    selectionEndBeats,
    selectionEndSeconds,
    lyricsEditController,
    showContextWindow,
    contextBeatsSetting,
    eventTrigger,
    replaceMode,
    extendFromBeats,
  ]);

  if (!generateMode) {
    return null;
  }

  const config = buttonConfigs[generateMode];

  const isRegenerate = !!regenerateParams;

  // Dynamic credit pricing based on selection length (< 30s → 4 credits)
  const selectionDurationSeconds = Math.max(
    0,
    (typeof selectionEndSeconds === 'number' ? selectionEndSeconds : 0) -
      (typeof selectionStartSeconds === 'number' ? selectionStartSeconds : 0)
  );
  const shortClipPricingEnabled =
    !!statsigClient?.checkGate('short-clip-pricing');
  const creditsLabel =
    shortClipPricingEnabled && selectionDurationSeconds < 30
      ? '4 credits'
      : '10 credits';

  return (
    <Tooltip
      key='infill'
      label={
        generateBlockingErrorMessage ||
        (iconOnly
          ? `${isRegenerate ? config.regenerateTooltip : config.tooltip} (${creditsLabel})`
          : creditsLabel)
      }
      placement={tooltipPlacement}
    >
      <Button
        disabled={!!generateBlockingErrorMessage || startingGeneration}
        shape={ButtonShape.Pill}
        variant={ButtonVariant.Aura}
        icon={
          startingGeneration ? (
            <SpinnerSVG />
          ) : (
            <config.IconComponent className='h-5 w-5' />
          )
        }
        onClick={handleClick}
        className={className}
        {...(otherProps as any)}
      >
        {iconOnly ? null : isRegenerate ? config.regenerateLabel : config.label}
      </Button>
    </Tooltip>
  );
}
