import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { setIn } from 'lodash-redux-immutability';
import React, {
  Dispatch,
  SetStateAction,
  memo,
  useCallback,
  useEffect,
  useMemo,
  useState,
} from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import LyricsModelSelector from '@/components/select/LyricsModelSelector';
import StudioContext from '@/components/studio/StudioContext';
import { Tooltip } from '@/components/tooltip/Tooltip';
import { useContextSelector } from '@/hooks/useContextSelector';
import { InfoIcon, MusicNoteSlashIcon, RotateLeftIcon } from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { PlanFeature } from '@/state/sessionStore';
import {
  CREATE_VERSION,
  DEFAULT_AUDIO_WEIGHT_VALUE,
  DEFAULT_CREATE_CONTROL_VALUE,
  MAX_CUSTOM_PROMPT_CHARS_LONGEST,
  MAX_NEGATIVE_STYLE_CHARS,
  SLIDER_INFO_TOOLTIPS,
  SLIDER_THRESHOLD_LABELS,
} from '@/utils/constants';
import { isFeatureEnabledForPlan } from '@/utils/session';
import { modelSupportsFeature } from '@/utils/utils';
import { allowOnlyNumbers, normalizeToScale, quantize } from '@/utils/utils';

import CreateFormContext from '../../v2/CreateFormContext';
import { getAllConditions } from '../../v2/actions/currentModeSetters';
import { CreateModes, LyricsInputModes, VocalGenders } from '../../v2/types';
import CreateCard from './CreateCard';
import CreateSlider from './CreateSlider';
import IconInput from './IconInput';
import { CollapsibleCardTitle } from './common';
import {
  CreateTheme,
  bigSpace,
  mediumSpace,
  smallButton,
  smallSpace,
} from './themes';
import { useSlidersAccess } from './useSlidersAccess';

const EMPTY_OBJECT = {};

interface AdvancedOptionsCardProps {
  lyricsMode?: LyricsInputModes;
  setLyricsMode?: Dispatch<SetStateAction<LyricsInputModes>>;
  showLyricsMode?: boolean;

  autoModePrompt?: string;
  setAutoModePrompt?: Dispatch<SetStateAction<string>>;

  lyricsModel?: string;
  setLyricsModel?: Dispatch<SetStateAction<string>>;

  expanded: boolean;
  setExpanded: Dispatch<SetStateAction<boolean>>;

  excludeStyles: string;
  setExcludeStyles: Dispatch<SetStateAction<string>>;

  weirdness: number;
  setWeirdness: Dispatch<SetStateAction<number>>;
  showWeirdness?: boolean;

  styleInfluence: number;
  setStyleInfluence: Dispatch<SetStateAction<number>>;
  showStyleInfluence?: boolean;

  audioInfluence: number;
  setAudioInfluence: Dispatch<SetStateAction<number>>;
  showAudioInfluence?: boolean;

  vocalGender: VocalGenders;
  setVocalGender: Dispatch<SetStateAction<VocalGenders>>;
  showVocalGender?: boolean;

  maxMode?: boolean;
  setMaxMode?: Dispatch<SetStateAction<boolean>>;
  showMaxMode?: boolean;

  replaceMode?: 'infill' | 'fixed_infill' | 'smart_infill';
  setReplaceMode?: Dispatch<
    SetStateAction<'infill' | 'fixed_infill' | 'smart_infill'>
  >;
  showReplaceMode?: boolean;

  model: string;

  onResetSliders?: () => void;

  nested?: boolean;
  fixed?: boolean;

  // Duration controls
  durationSeconds?: number | null;
  setDurationSeconds?: (seconds: number | null) => void;
  showDurationSeconds?: boolean;
}

const SliderReadout = styled.div<{ dangerZone?: boolean }>`
  font-size: 12px;
  font-weight: 500;
  color: ${({ dangerZone }) =>
    dangerZone
      ? 'var(--color-accent-error)'
      : 'var(--color-foreground-primary)'};
  text-align: right;
  flex-grow: 1;
  min-width: 40px;
  cursor: pointer;
  user-select: none;

  &:hover {
    opacity: 0.8;
  }
`;

const EditableInput = styled.input`
  font-size: 12px;
  font-weight: 500;
  color: var(--color-foreground-primary);
  text-align: right;
  background: transparent;
  border: none;
  outline: none;
  width: 40px;
  padding: 0;
  margin: 0;
  font-family: inherit;
`;

const AdvancedOptionsContent = styled.div`
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: 0;
  overflow: hidden;
  padding: 0 ${mediumSpace}px ${mediumSpace}px ${mediumSpace}px;
  gap: ${mediumSpace}px;
`;

const OptionWrapper = styled.div<{ disabled?: boolean }>`
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: ${smallSpace}px;
  border-radius: 12px;
  padding: ${smallSpace}px ${bigSpace}px;
  min-height: calc(${smallButton}px + ${bigSpace}px);
  background-color: var(--color-background-primary);
  color: var(--color-foreground-primary);
  font-size: 12px;
  opacity: ${({ disabled }) => (disabled ? 0.5 : 1)};
`;

const OptionInfoWrapper = styled.div`
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 4px;
  min-width: 125px;
`;

const OptionPickerWrapper = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: flex-end;
  flex-grow: 1;
  gap: 2px;
  margin-right: -${smallSpace}px;

  button {
    padding: 4px 8px;
    border-radius: 8px;

    &[data-selected='true'] {
      background-color: var(--color-background-fog-thick);
    }
  }
`;

const AdvancedOptionsCard: React.FC<AdvancedOptionsCardProps> = memo(
  function AdvancedOptionsCard({
    lyricsMode,
    setLyricsMode,
    showLyricsMode,

    autoModePrompt,
    setAutoModePrompt,

    lyricsModel,
    setLyricsModel,

    expanded,
    setExpanded,

    excludeStyles,
    setExcludeStyles,

    weirdness,
    setWeirdness,
    showWeirdness,

    styleInfluence,
    setStyleInfluence,
    showStyleInfluence,

    audioInfluence,
    setAudioInfluence,
    showAudioInfluence,

    vocalGender,
    setVocalGender,
    showVocalGender,

    maxMode,
    setMaxMode,
    showMaxMode,

    replaceMode,
    setReplaceMode,
    showReplaceMode,

    model,

    onResetSliders,
    nested,
    fixed,
    durationSeconds,
    setDurationSeconds,
    showDurationSeconds = true,
  }) {
    const theme = useTheme() as CreateTheme;
    const { session } = useStores();

    const [localWeirdness, setLocalWeirdness] = useState(weirdness);
    const [localStyleInfluence, setLocalStyleInfluence] =
      useState(styleInfluence);
    const [localAudioInfluence, setLocalAudioInfluence] =
      useState(audioInfluence);
    const { showUpsellIfRestricted } = useSlidersAccess();

    const [editingWeirdness, setEditingWeirdness] = useState(false);
    const [editingStyleInfluence, setEditingStyleInfluence] = useState(false);
    const [editingAudioInfluence, setEditingAudioInfluence] = useState(false);

    // Track raw input values during editing
    const [inputWeirdness, setInputWeirdness] = useState(weirdness.toString());
    const [inputStyleInfluence, setInputStyleInfluence] = useState(
      styleInfluence.toString()
    );
    const [inputAudioInfluence, setInputAudioInfluence] = useState(
      audioInfluence.toString()
    );

    useEffect(() => {
      setLocalWeirdness(weirdness);
      setInputWeirdness(Math.round(weirdness).toString());
    }, [weirdness]);

    useEffect(() => {
      setLocalStyleInfluence(styleInfluence);
      setInputStyleInfluence(Math.round(styleInfluence).toString());
    }, [styleInfluence]);

    useEffect(() => {
      setLocalAudioInfluence(audioInfluence);
      setInputAudioInfluence(Math.round(audioInfluence).toString());
    }, [audioInfluence]);

    const replaceModeName = useMemo(() => {
      if (replaceMode === 'infill') {
        return 'Classic';
      } else if (replaceMode === 'fixed_infill') {
        return 'Fixed';
      } else {
        return 'Smart';
      }
    }, [replaceMode]);

    const handlePercentageEdit = (
      inputValue: string,
      setter: (value: number) => void,
      setEditing: (editing: boolean) => void
    ) => {
      const numValue = parseFloat(inputValue);
      if (!isNaN(numValue)) {
        const clampedValue = Math.max(0, Math.min(100, numValue));
        setter(clampedValue);
      }
      setEditing(false);
    };

    const handlePercentageKeyDown = (
      e: React.KeyboardEvent,
      setEditing: (editing: boolean) => void,
      inputValue: string,
      setter: (value: number) => void
    ) => {
      if (e.key === 'Enter') {
        const numValue = parseFloat(inputValue);
        if (!isNaN(numValue)) {
          const clampedValue = Math.max(0, Math.min(100, numValue));
          setter(clampedValue);
        }
        setEditing(false);
      } else if (e.key === 'Escape') {
        setEditing(false);
      }
    };

    // Duration slider state (2:00–8:00 in 15s steps)
    const [localDurationSeconds, setLocalDurationSeconds] = useState<
      number | null
    >(durationSeconds ?? null);
    useEffect(() => {
      setLocalDurationSeconds(durationSeconds ?? null);
    }, [durationSeconds]);
    // Track if the user has interacted with the duration control (derived)
    // Show time while dragging (localDurationSeconds) and after commit (durationSeconds)
    const hasTouchedDuration = durationSeconds != null;
    const quantizeToFifteenSeconds = useCallback((v01: number) => {
      const min = 120;
      const max = 480;
      const clamped01 = Math.max(0, Math.min(1, v01));
      const raw = normalizeToScale(clamped01, 0, 1, min, max);
      const stepped = quantize(raw, 15);
      return Math.max(min, Math.min(max, stepped));
    }, []);
    const toSliderValue = useCallback((secs: number) => {
      const v01 = normalizeToScale(secs, 120, 480, 0, 1);
      return Math.max(0, Math.min(1, v01));
    }, []);
    const formatMmSs = useCallback((secs: number) => {
      const m = Math.floor(secs / 60);
      const s = Math.floor(secs % 60)
        .toString()
        .padStart(2, '0');
      return `${m}:${s}`;
    }, []);

    const durationEnabled = modelSupportsFeature(
      model,
      session.billingModels,
      'create_control_sliders'
    );

    const durationGateEnabled = session.isFeatureAllowed(
      'song-duration-control'
    ).enabled;

    return (
      <CreateCard
        nested={nested}
        title={
          <CollapsibleCardTitle
            title='Advanced Options'
            subtitle={[
              showLyricsMode &&
              lyricsMode &&
              lyricsMode !== LyricsInputModes.MANUAL
                ? `${lyricsMode === LyricsInputModes.AUTO ? 'Auto Lyrics' : lyricsMode === LyricsInputModes.MUMBLE_MODE ? 'Mumble Mode' : ''}`
                : '',
              showReplaceMode && replaceMode !== 'smart_infill'
                ? `${replaceModeName} Replace Mode`
                : '',
              excludeStyles
                ? `Exclude "${excludeStyles.replace(/\n/g, ' / ')}"`
                : '',
            ]
              .filter(Boolean)
              .join(' / ')}
            expanded={expanded}
          />
        }
        collapsible={!fixed}
        expanded={expanded}
        setExpanded={setExpanded}
        headerContent={
          onResetSliders &&
          (weirdness !== DEFAULT_CREATE_CONTROL_VALUE ||
            styleInfluence !== DEFAULT_CREATE_CONTROL_VALUE ||
            audioInfluence !== DEFAULT_AUDIO_WEIGHT_VALUE) ? (
            <Tooltip label='Reset All'>
              <Button
                className={theme.tailwind.bigButtonPadding}
                shape={ButtonShape.Pill}
                onClick={onResetSliders}
                icon={<RotateLeftIcon className='h-4 w-4' />}
              />
            </Tooltip>
          ) : null
        }
      >
        <AdvancedOptionsContent>
          {isFeatureEnabledForPlan(session, PlanFeature.NegativeTags) && (
            <OptionWrapper>
              <IconInput
                icon={<MusicNoteSlashIcon className='h-4 w-4' />}
                value={excludeStyles}
                onChange={(e) => setExcludeStyles(e.target.value)}
                placeholder='Exclude styles'
                maxLength={MAX_NEGATIVE_STYLE_CHARS}
              />
            </OptionWrapper>
          )}

          {showReplaceMode && (
            <OptionWrapper>
              <OptionInfoWrapper>
                <span>Replace Mode</span>
                <Tooltip
                  label={
                    <>
                      Fixed mode works better for 1-2 second selections, but is
                      less stable over long selections.
                      <br />
                      Leave blank to automatically choose based on duration.
                    </>
                  }
                >
                  <InfoIcon className='h-4 w-4 opacity-50' />
                </Tooltip>
              </OptionInfoWrapper>
              <OptionPickerWrapper>
                <Button
                  className={`${replaceMode === 'infill' ? 'text-foreground-primary' : 'text-gray-400'} mr-[1px] hover:text-foreground-primary`}
                  size={ButtonSize.Mini}
                  variant={
                    replaceMode === 'infill'
                      ? ButtonVariant.Standard
                      : ButtonVariant.Tertiary
                  }
                  onClick={() => {
                    if (replaceMode === 'infill') {
                      setReplaceMode?.('smart_infill');
                    } else {
                      setReplaceMode?.('infill');
                    }
                  }}
                >
                  Classic
                </Button>
                <Button
                  className={`${replaceMode === 'fixed_infill' ? 'text-foreground-primary' : 'text-gray-400'} mr-[1px] hover:text-foreground-primary`}
                  size={ButtonSize.Mini}
                  variant={
                    replaceMode === 'fixed_infill'
                      ? ButtonVariant.Standard
                      : ButtonVariant.Tertiary
                  }
                  onClick={() => {
                    if (replaceMode === 'fixed_infill') {
                      setReplaceMode?.('smart_infill');
                    } else {
                      setReplaceMode?.('fixed_infill');
                    }
                  }}
                >
                  Fixed
                </Button>
              </OptionPickerWrapper>
            </OptionWrapper>
          )}

          {showVocalGender && (
            <OptionWrapper>
              <OptionInfoWrapper>
                <span>Vocal Gender</span>
                <Tooltip label={'Change the gender of the generated vocals'}>
                  <InfoIcon className='h-4 w-4 opacity-50' />
                </Tooltip>
              </OptionInfoWrapper>
              <OptionPickerWrapper>
                <Button
                  className={`${vocalGender === VocalGenders.MALE ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                  size={ButtonSize.Mini}
                  variant={
                    vocalGender === VocalGenders.MALE
                      ? ButtonVariant.Standard
                      : ButtonVariant.Tertiary
                  }
                  data-selected={vocalGender === VocalGenders.MALE}
                  onClick={() => {
                    if (vocalGender === VocalGenders.MALE) {
                      setVocalGender(VocalGenders.UNSPECIFIED);
                    } else {
                      setVocalGender(VocalGenders.MALE);
                    }
                  }}
                >
                  Male
                </Button>
                <Button
                  className={`${vocalGender === VocalGenders.FEMALE ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                  size={ButtonSize.Mini}
                  variant={
                    vocalGender === VocalGenders.FEMALE
                      ? ButtonVariant.Standard
                      : ButtonVariant.Tertiary
                  }
                  data-selected={vocalGender === VocalGenders.FEMALE}
                  onClick={() => {
                    if (vocalGender === VocalGenders.FEMALE) {
                      setVocalGender(VocalGenders.UNSPECIFIED);
                    } else {
                      setVocalGender(VocalGenders.FEMALE);
                    }
                  }}
                >
                  Female
                </Button>
              </OptionPickerWrapper>
            </OptionWrapper>
          )}

          {showLyricsMode && (
            <OptionWrapper
              style={{
                flexWrap: 'wrap',
                height: 'auto',
                position: 'relative',
                padding: '16px 16px',
              }}
            >
              <OptionInfoWrapper>
                <span>Lyrics Mode</span>
                <Tooltip
                  label={
                    session.flags?.['mumble-mode']
                      ? 'Choose how to control lyrics: write manually, use AI prompt, or sing without lyrics'
                      : 'Choose how to control lyrics: write manually, or use AI prompt'
                  }
                >
                  <InfoIcon className='h-4 w-4 opacity-50' />
                </Tooltip>
              </OptionInfoWrapper>
              <OptionPickerWrapper>
                <Tooltip label='Sings the lyrics in the lyrics box'>
                  <Button
                    className={`${lyricsMode === LyricsInputModes.MANUAL ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                    size={ButtonSize.Mini}
                    variant={
                      lyricsMode === LyricsInputModes.MANUAL
                        ? ButtonVariant.Standard
                        : ButtonVariant.Tertiary
                    }
                    data-selected={lyricsMode === LyricsInputModes.MANUAL}
                    onClick={() => {
                      const previousMode = lyricsMode;
                      setLyricsMode?.(LyricsInputModes.MANUAL);
                      logWebUserEvent({
                        actionName: 'ChangeLyricsMode',
                        context: {
                          createMode: 'custom',
                          lyricsModeBefore: previousMode || 'custom',
                          lyricsModeAfter: 'custom',
                          createVersion: CREATE_VERSION,
                        },
                      });
                    }}
                  >
                    Manual
                  </Button>
                </Tooltip>
                {session.flags?.['mumble-mode'] && (
                  <Tooltip label='Mumbles gibberish lyrics'>
                    <Button
                      className={`${lyricsMode === LyricsInputModes.MUMBLE_MODE ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                      size={ButtonSize.Mini}
                      variant={
                        lyricsMode === LyricsInputModes.MUMBLE_MODE
                          ? ButtonVariant.Standard
                          : ButtonVariant.Tertiary
                      }
                      data-selected={
                        lyricsMode === LyricsInputModes.MUMBLE_MODE
                      }
                      onClick={() => {
                        const previousMode = lyricsMode;
                        setLyricsMode?.(LyricsInputModes.MUMBLE_MODE);
                        logWebUserEvent({
                          actionName: 'ChangeLyricsMode',
                          context: {
                            createMode: 'custom',
                            lyricsModeBefore: previousMode || 'custom',
                            lyricsModeAfter: 'mumble_mode',
                            createVersion: CREATE_VERSION,
                          },
                        });
                      }}
                    >
                      Mumble
                    </Button>
                  </Tooltip>
                )}
                <Tooltip label='Suno writes new lyrics for every generation'>
                  <Button
                    className={`${lyricsMode === LyricsInputModes.AUTO ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                    size={ButtonSize.Mini}
                    variant={
                      lyricsMode === LyricsInputModes.AUTO
                        ? ButtonVariant.Standard
                        : ButtonVariant.Tertiary
                    }
                    data-selected={lyricsMode === LyricsInputModes.AUTO}
                    onClick={() => {
                      const previousMode = lyricsMode;
                      setLyricsMode?.(LyricsInputModes.AUTO);
                      logWebUserEvent({
                        actionName: 'ChangeLyricsMode',
                        context: {
                          createMode: 'custom',
                          lyricsModeBefore: previousMode || 'custom',
                          lyricsModeAfter: 'auto',
                          createVersion: CREATE_VERSION,
                        },
                      });
                    }}
                  >
                    Auto
                  </Button>
                </Tooltip>
              </OptionPickerWrapper>
              {lyricsMode === LyricsInputModes.AUTO &&
                setAutoModePrompt &&
                setLyricsModel && (
                  <>
                    <textarea
                      className='min-h-16 w-full border-none bg-transparent text-sm outline-none'
                      value={autoModePrompt || ''}
                      onChange={(e) => setAutoModePrompt?.(e.target.value)}
                      placeholder='Describe the lyrics you want, or share a theme or topic. Suno will write new lyrics for every generation.'
                      maxLength={MAX_CUSTOM_PROMPT_CHARS_LONGEST}
                      aria-label='Auto lyrics prompt'
                    />
                    <div className='-mb-2 flex w-full justify-end'>
                      <LyricsModelSelector
                        value={lyricsModel || 'default'}
                        className='-mr-2'
                        onSetValue={(newValue: string) => {
                          const previousModel = lyricsModel;
                          setLyricsModel(newValue);
                          logWebUserEvent({
                            actionName: 'ChangeLyricsModel',
                            context: {
                              modelBefore: previousModel || 'default',
                              modelAfter: newValue,
                              source: 'advanced_options_card',
                              createVersion: CREATE_VERSION,
                            },
                          });
                        }}
                        variant={ButtonVariant.Secondary}
                        size={ButtonSize.Mini}
                        menuClassName='bg-background-secondary'
                      />
                    </div>
                  </>
                )}
            </OptionWrapper>
          )}

          {showMaxMode && (
            <OptionWrapper>
              <OptionInfoWrapper>
                <span>Max Mode</span>
                <Tooltip
                  label={
                    'Uses more compute to maximize quality throughout the song. Costs an addition 5 credits per song.'
                  }
                >
                  <InfoIcon className='h-4 w-4 opacity-50' />
                </Tooltip>
              </OptionInfoWrapper>
              <OptionPickerWrapper>
                <Button
                  className={`${!maxMode ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                  size={ButtonSize.Mini}
                  variant={
                    !maxMode ? ButtonVariant.Standard : ButtonVariant.Tertiary
                  }
                  data-selected={!maxMode}
                  onClick={() => {
                    setMaxMode?.(false);
                  }}
                >
                  Off
                </Button>
                <Button
                  className={`${maxMode ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                  size={ButtonSize.Mini}
                  variant={
                    maxMode ? ButtonVariant.Standard : ButtonVariant.Tertiary
                  }
                  data-selected={maxMode}
                  onClick={() => {
                    setMaxMode?.(true);
                  }}
                >
                  On
                </Button>
              </OptionPickerWrapper>
            </OptionWrapper>
          )}

          <OptionWrapper disabled={!showWeirdness}>
            <OptionInfoWrapper>
              <span>Weirdness</span>
              {weirdness !== DEFAULT_CREATE_CONTROL_VALUE ? (
                <Tooltip label={'Reset to default'}>
                  <RotateLeftIcon
                    className='h-4 w-4 cursor-pointer opacity-50 hover:opacity-100'
                    onClick={() => {
                      setWeirdness(DEFAULT_CREATE_CONTROL_VALUE);
                      setLocalWeirdness(DEFAULT_CREATE_CONTROL_VALUE);
                    }}
                  />
                </Tooltip>
              ) : (
                <Tooltip label={SLIDER_INFO_TOOLTIPS.weirdness_constraint}>
                  <InfoIcon className='h-4 w-4 opacity-50' />
                </Tooltip>
              )}
            </OptionInfoWrapper>
            <CreateSlider
              value={weirdness / 100}
              disabled={!showWeirdness}
              defaultValue={DEFAULT_CREATE_CONTROL_VALUE / 100}
              onChange={(value) => setLocalWeirdness(value * 100)}
              onCommit={(value) => setWeirdness(value * 100)}
              thresholds={SLIDER_THRESHOLD_LABELS.weirdness}
              showUpsellIfRestricted={showUpsellIfRestricted}
              ariaLabel='Weirdness'
            />
            {editingWeirdness ? (
              <EditableInput
                type='text'
                value={inputWeirdness}
                onChange={(e) => {
                  if (showUpsellIfRestricted()) {
                    e.stopPropagation();
                    e.preventDefault();
                    return;
                  }
                  const value = e.target.value;
                  if (allowOnlyNumbers(value)) {
                    setInputWeirdness(value);
                  }
                }}
                onBlur={() =>
                  handlePercentageEdit(
                    inputWeirdness,
                    setWeirdness,
                    setEditingWeirdness
                  )
                }
                onKeyDown={(e) =>
                  handlePercentageKeyDown(
                    e,
                    setEditingWeirdness,
                    inputWeirdness,
                    setWeirdness
                  )
                }
                autoFocus
              />
            ) : (
              <SliderReadout
                dangerZone={localWeirdness > 85 || localWeirdness < 15}
                onMouseDown={(e) => {
                  if (showUpsellIfRestricted()) {
                    e.stopPropagation();
                    e.preventDefault();
                  }
                }}
                onDoubleClick={() => setEditingWeirdness(true)}
              >
                {localWeirdness.toFixed(0)}%
              </SliderReadout>
            )}
          </OptionWrapper>

          <OptionWrapper disabled={!showStyleInfluence}>
            <OptionInfoWrapper>
              <span>Style Influence</span>
              {styleInfluence !== DEFAULT_CREATE_CONTROL_VALUE ? (
                <Tooltip label={'Reset to default'}>
                  <RotateLeftIcon
                    className='h-4 w-4 cursor-pointer opacity-50 hover:opacity-100'
                    onClick={() => {
                      setStyleInfluence(DEFAULT_CREATE_CONTROL_VALUE);
                      setLocalStyleInfluence(DEFAULT_CREATE_CONTROL_VALUE);
                    }}
                  />
                </Tooltip>
              ) : (
                <Tooltip label={SLIDER_INFO_TOOLTIPS.style_weight}>
                  <InfoIcon className='h-4 w-4 opacity-50' />
                </Tooltip>
              )}
            </OptionInfoWrapper>
            <CreateSlider
              disabled={!showStyleInfluence}
              value={styleInfluence / 100}
              defaultValue={DEFAULT_CREATE_CONTROL_VALUE / 100}
              onChange={(value) => setLocalStyleInfluence(value * 100)}
              onCommit={(value) => setStyleInfluence(value * 100)}
              thresholds={SLIDER_THRESHOLD_LABELS.styleInfluence}
              showUpsellIfRestricted={showUpsellIfRestricted}
              ariaLabel='Style Influence'
            />
            {editingStyleInfluence ? (
              <EditableInput
                type='text'
                value={inputStyleInfluence}
                onChange={(e) => {
                  if (showUpsellIfRestricted()) {
                    e.stopPropagation();
                    e.preventDefault();
                    return;
                  }
                  const value = e.target.value;
                  if (allowOnlyNumbers(value)) {
                    setInputStyleInfluence(value);
                  }
                }}
                onBlur={() =>
                  handlePercentageEdit(
                    inputStyleInfluence,
                    setStyleInfluence,
                    setEditingStyleInfluence
                  )
                }
                onKeyDown={(e) =>
                  handlePercentageKeyDown(
                    e,
                    setEditingStyleInfluence,
                    inputStyleInfluence,
                    setStyleInfluence
                  )
                }
                autoFocus
              />
            ) : (
              <SliderReadout
                dangerZone={
                  localStyleInfluence > 85 || localStyleInfluence < 15
                }
                onMouseDown={(e) => {
                  if (showUpsellIfRestricted()) {
                    e.stopPropagation();
                    e.preventDefault();
                  }
                }}
                onDoubleClick={() => setEditingStyleInfluence(true)}
              >
                {localStyleInfluence.toFixed(0)}%
              </SliderReadout>
            )}
          </OptionWrapper>

          {showAudioInfluence && (
            <OptionWrapper>
              <OptionInfoWrapper>
                <span>Audio Influence</span>
                <Tooltip label={SLIDER_INFO_TOOLTIPS.audio_weight}>
                  <InfoIcon className='h-4 w-4 opacity-50' />
                </Tooltip>
              </OptionInfoWrapper>
              <CreateSlider
                value={audioInfluence / 100}
                defaultValue={DEFAULT_AUDIO_WEIGHT_VALUE / 100}
                onChange={(value) => setLocalAudioInfluence(value * 100)}
                onCommit={(value) => setAudioInfluence(value * 100)}
                thresholds={SLIDER_THRESHOLD_LABELS.audioInfluence}
                showUpsellIfRestricted={showUpsellIfRestricted}
                ariaLabel='Audio Influence'
              />
              {editingAudioInfluence ? (
                <EditableInput
                  type='text'
                  value={inputAudioInfluence}
                  onChange={(e) => {
                    if (showUpsellIfRestricted()) {
                      e.stopPropagation();
                      e.preventDefault();
                      return;
                    }
                    const value = e.target.value;
                    if (allowOnlyNumbers(value)) {
                      setInputAudioInfluence(value);
                    }
                  }}
                  onBlur={() =>
                    handlePercentageEdit(
                      inputAudioInfluence,
                      setAudioInfluence,
                      setEditingAudioInfluence
                    )
                  }
                  onKeyDown={(e) =>
                    handlePercentageKeyDown(
                      e,
                      setEditingAudioInfluence,
                      inputAudioInfluence,
                      setAudioInfluence
                    )
                  }
                  autoFocus
                />
              ) : (
                <SliderReadout
                  dangerZone={
                    localAudioInfluence > 85 || localAudioInfluence < 15
                  }
                  onMouseDown={(e) => {
                    if (showUpsellIfRestricted()) {
                      e.stopPropagation();
                      e.preventDefault();
                    }
                  }}
                  onDoubleClick={() => setEditingAudioInfluence(true)}
                >
                  {localAudioInfluence.toFixed(0)}%
                </SliderReadout>
              )}
            </OptionWrapper>
          )}

          {durationGateEnabled &&
            showDurationSeconds &&
            !!setDurationSeconds && (
              <OptionWrapper disabled={!durationEnabled}>
                <OptionInfoWrapper>
                  <span>Duration</span>
                  {hasTouchedDuration ? (
                    <Tooltip label={'Reset to auto'}>
                      <RotateLeftIcon
                        className='h-4 w-4 cursor-pointer opacity-50 hover:opacity-100'
                        onClick={() => {
                          setLocalDurationSeconds(null);
                          setDurationSeconds?.(null);
                        }}
                      />
                    </Tooltip>
                  ) : (
                    <Tooltip label={'Desired song length (2–8 minutes).'}>
                      <InfoIcon className='h-4 w-4 opacity-50' />
                    </Tooltip>
                  )}
                </OptionInfoWrapper>
                {hasTouchedDuration ? (
                  <>
                    <CreateSlider
                      value={
                        localDurationSeconds != null
                          ? Math.max(
                              0,
                              Math.min(1, toSliderValue(localDurationSeconds))
                            )
                          : 0
                      }
                      defaultValue={0}
                      disabled={!durationEnabled}
                      onChange={(v) => {
                        const q = quantizeToFifteenSeconds(v);
                        setLocalDurationSeconds(q);
                      }}
                      onCommit={(v) => {
                        const q = quantizeToFifteenSeconds(v);
                        setDurationSeconds?.(q);
                        setLocalDurationSeconds(q);
                      }}
                      ariaLabel='Duration'
                    />
                    <SliderReadout>
                      {localDurationSeconds != null
                        ? formatMmSs(localDurationSeconds)
                        : '-:-'}
                    </SliderReadout>
                  </>
                ) : (
                  <OptionPickerWrapper>
                    <Button
                      className={`${hasTouchedDuration ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                      size={ButtonSize.Mini}
                      variant={
                        hasTouchedDuration
                          ? ButtonVariant.Standard
                          : ButtonVariant.Tertiary
                      }
                      data-selected={hasTouchedDuration}
                      onClick={() => {
                        const defaultDuration = 180; // 3 minutes
                        setLocalDurationSeconds(defaultDuration);
                        setDurationSeconds?.(defaultDuration);
                      }}
                      disabled={!durationEnabled}
                    >
                      Custom
                    </Button>
                    <Button
                      className={`${!hasTouchedDuration ? 'text-foreground-primary' : 'text-gray-400'} mr-px text-xs hover:text-foreground-primary`}
                      size={ButtonSize.Mini}
                      variant={
                        !hasTouchedDuration
                          ? ButtonVariant.Standard
                          : ButtonVariant.Tertiary
                      }
                      data-selected={!hasTouchedDuration}
                      onClick={() => {
                        setLocalDurationSeconds(null);
                        setDurationSeconds?.(null);
                      }}
                      disabled={!durationEnabled}
                    >
                      Auto
                    </Button>
                  </OptionPickerWrapper>
                )}
              </OptionWrapper>
            )}
        </AdvancedOptionsContent>
      </CreateCard>
    );
  }
);

export const CustomAdvancedOptionsCard = () => {
  const { session } = useStores();
  const [excludeStyles, setExcludeStyles] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<string>([CreateModes.CUSTOM, 'excludeStyles'])
  );
  const [weirdness, setWeirdness] = useContextSelector(
    CreateFormContext,
    (context) => context.selectState<number>([CreateModes.CUSTOM, 'weirdness'])
  );
  const [styleInfluence, setStyleInfluence] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<number>([CreateModes.CUSTOM, 'styleInfluence'])
  );
  const [audioInfluence, setAudioInfluence] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<number>([CreateModes.CUSTOM, 'audioInfluence'])
  );
  const [vocalGender, setVocalGender] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<VocalGenders>([CreateModes.CUSTOM, 'vocalGender'])
  );
  const [maxMode, setMaxMode] = useContextSelector(
    CreateFormContext,
    (context) => context.selectState<boolean>([CreateModes.CUSTOM, 'maxMode'])
  );
  const [expanded, setExpanded] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<boolean>([
        CreateModes.CUSTOM,
        'advancedOptionsExpanded',
      ])
  );
  const [durationSeconds] = useContextSelector(CreateFormContext, (context) =>
    context.selectState<number>([CreateModes.CUSTOM, 'durationSeconds'])
  );
  const setFormState = useContextSelector(
    CreateFormContext,
    (context) => context.setState
  );
  const setDurationSeconds = useCallback(
    (seconds: number | null) => {
      setFormState((s) =>
        setIn(s, [CreateModes.CUSTOM, 'durationSeconds'], seconds)
      );
    },
    [setFormState]
  );
  const [lyricsMode, setLyricsMode] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<LyricsInputModes>([CreateModes.CUSTOM, 'lyricsMode'])
  );

  const [autoModePrompt, setAutoModePrompt] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<string>([CreateModes.CUSTOM, 'lyricsPrompt'])
  );

  const [lyricsModel, setLyricsModel] = useContextSelector(
    CreateFormContext,
    (context) => context.selectState<string>(['global', 'lyricsModel'])
  );

  const model = useContextSelector(
    CreateFormContext,
    (context) => context.state.global.model
  );

  const showVocalGender = model !== 'v2';
  const showWeirdness = modelSupportsFeature(
    model,
    session.billingModels,
    'create_control_sliders'
  );
  const showStyleInfluence = showWeirdness;

  const showAudioInfluence = useContextSelector(CreateFormContext, (ctx) => {
    const allConditions = getAllConditions(ctx.state) || EMPTY_OBJECT;
    // Only count keys that have actual values (not undefined/null)
    return Object.keys(allConditions).some(
      (key) => (allConditions as any)[key] != null
    );
  });

  const showMaxMode =
    session.isFeatureAllowed('max-mode').enabled &&
    model.toLowerCase().includes('crow');

  useEffect(() => {
    if (!showMaxMode && maxMode) {
      setMaxMode(false);
    }
  }, [showMaxMode, maxMode, setMaxMode]);

  const handleResetSliders = useCallback(() => {
    setWeirdness(DEFAULT_CREATE_CONTROL_VALUE);
    setStyleInfluence(DEFAULT_CREATE_CONTROL_VALUE);
    setAudioInfluence(DEFAULT_AUDIO_WEIGHT_VALUE);
  }, [setWeirdness, setStyleInfluence, setAudioInfluence]);

  return (
    <AdvancedOptionsCard
      lyricsMode={lyricsMode}
      setLyricsMode={setLyricsMode}
      showLyricsMode={true}
      autoModePrompt={autoModePrompt}
      setAutoModePrompt={setAutoModePrompt}
      lyricsModel={lyricsModel}
      setLyricsModel={setLyricsModel}
      excludeStyles={excludeStyles}
      setExcludeStyles={setExcludeStyles}
      weirdness={weirdness}
      setWeirdness={setWeirdness}
      showWeirdness={showWeirdness}
      styleInfluence={styleInfluence}
      setStyleInfluence={setStyleInfluence}
      showStyleInfluence={showStyleInfluence}
      audioInfluence={audioInfluence}
      setAudioInfluence={setAudioInfluence}
      showAudioInfluence={showAudioInfluence}
      vocalGender={vocalGender}
      setVocalGender={setVocalGender}
      showVocalGender={showVocalGender}
      maxMode={maxMode}
      setMaxMode={setMaxMode}
      showMaxMode={showMaxMode}
      expanded={expanded}
      setExpanded={setExpanded}
      model={model}
      onResetSliders={handleResetSliders}
      durationSeconds={durationSeconds}
      setDurationSeconds={setDurationSeconds}
      showDurationSeconds={true}
    />
  );
};

export const StudioAdvancedOptionsCard = () => {
  const { session } = useStores();
  const [excludeStyles, setExcludeStyles] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<string>([CreateModes.STUDIO_EDIT, 'excludeStyles'])
  );
  const [weirdness, setWeirdness] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<number>([CreateModes.STUDIO_EDIT, 'weirdness'])
  );
  const [styleInfluence, setStyleInfluence] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<number>([CreateModes.STUDIO_EDIT, 'styleInfluence'])
  );
  const [audioInfluence, setAudioInfluence] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<number>([CreateModes.STUDIO_EDIT, 'audioInfluence'])
  );
  const [vocalGender, setVocalGender] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<VocalGenders>([
        CreateModes.STUDIO_EDIT,
        'vocalGender',
      ])
  );
  const [maxMode, setMaxMode] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<boolean>([CreateModes.STUDIO_EDIT, 'maxMode'])
  );
  const [expanded, setExpanded] = useContextSelector(
    CreateFormContext,
    (context) =>
      context.selectState<boolean>([
        CreateModes.STUDIO_EDIT,
        'advancedOptionsExpanded',
      ])
  );

  const replaceMode = useContextSelector(
    StudioContext,
    (context) => context.replaceMode
  );
  const setReplaceMode = useContextSelector(
    StudioContext,
    (context) => context.setReplaceMode
  );

  const model = useContextSelector(
    CreateFormContext,
    (context) => context.state.global.model
  );

  // const showVocalGender = model !== 'v2';
  const showVocalGender = false;
  const showWeirdness =
    (model.includes('auk') || model.includes('bluejay')) &&
    replaceMode === 'infill';
  const showStyleInfluence = showWeirdness;

  const showAudioInfluence = useContextSelector(CreateFormContext, (ctx) => {
    const allConditions = getAllConditions(ctx.state) || EMPTY_OBJECT;
    // Only count keys that have actual values (not undefined/null)
    return Object.keys(allConditions).some(
      (key) => (allConditions as any)[key] != null
    );
  });

  const showMaxMode =
    session.isFeatureAllowed('max-mode').enabled &&
    model.toLowerCase().includes('crow');

  useEffect(() => {
    if (!showMaxMode && maxMode) {
      setMaxMode(false);
    }
  }, [showMaxMode, maxMode, setMaxMode]);

  const handleResetSliders = () => {
    setWeirdness(DEFAULT_CREATE_CONTROL_VALUE);
    setStyleInfluence(DEFAULT_CREATE_CONTROL_VALUE);
    setAudioInfluence(DEFAULT_AUDIO_WEIGHT_VALUE);
  };

  return (
    <AdvancedOptionsCard
      showLyricsMode={false}
      excludeStyles={excludeStyles}
      setExcludeStyles={setExcludeStyles}
      weirdness={weirdness}
      setWeirdness={setWeirdness}
      showWeirdness={showWeirdness}
      styleInfluence={styleInfluence}
      setStyleInfluence={setStyleInfluence}
      showStyleInfluence={showStyleInfluence}
      audioInfluence={audioInfluence}
      setAudioInfluence={setAudioInfluence}
      showAudioInfluence={showAudioInfluence}
      vocalGender={vocalGender}
      setVocalGender={setVocalGender}
      showVocalGender={showVocalGender}
      maxMode={maxMode}
      setMaxMode={setMaxMode}
      showMaxMode={showMaxMode}
      expanded={expanded}
      setExpanded={setExpanded}
      replaceMode={replaceMode}
      setReplaceMode={setReplaceMode}
      showReplaceMode
      model={model}
      onResetSliders={handleResetSliders}
      showDurationSeconds={false}
    />
  );
};

export default AdvancedOptionsCard;
