import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import { twMerge } from 'tailwind-merge';

import { useStores } from '@/app/(root)/AppProviders';
import Button, { ButtonShape, ButtonSize } from '@/components/button/Button';
import { ModalTypes } from '@/components/modal/constants/ModalTypes';
import { TextInput } from '@/components/textarea/TextInput';
import {
  CaretDownIcon,
  CaretUpIcon,
  EditUndoIcon,
  MusicSlashIcon,
} from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { ControlSliderKey } from '@/state/createV2Store';
import { PlanFeature } from '@/state/sessionStore';
import { FeatureKey } from '@/state/sessionStore';
import {
  CREATE_VERSION,
  DEFAULT_AUDIO_WEIGHT_VALUE,
  DEFAULT_CREATE_CONTROL_VALUE,
  SLIDER_INFO_TOOLTIPS,
  SLIDER_VALUE_TOOLTIPS,
} from '@/utils/constants';
import { isFeatureEnabledForPlan } from '@/utils/session';
import { isSubscriber } from '@/utils/session';
import { modelSupportsFeature } from '@/utils/utils';

import { FakeSlider } from './FakeSlider';
import { SimpleSlider } from './SimpleSlider';
import { getTagsMaxLengthForModel } from './utils';

type Props = {
  isOpen: boolean;
  onOpenChange: (isOpen: boolean) => void;
  withExcludeStyles?: boolean;
  sliders: { [key in ControlSliderKey]?: number };
  onSliderValueChanged: (
    sliderKey: ControlSliderKey,
    sliderValue: number
  ) => void;
  onResetSliders: () => void;
  modelName: string;
  negativeTags?: string;
  onChangeNegativeTags?: (negativeTags: string) => void;
  hasAudioCondition?: boolean;
};

export const AdvancedOptions = observer(
  ({
    isOpen,
    onOpenChange,
    withExcludeStyles = false,
    sliders,
    onSliderValueChanged,
    onResetSliders,
    modelName,
    negativeTags,
    onChangeNegativeTags,
    hasAudioCondition,
  }: Props) => {
    const { session, menus, createV2 } = useStores();

    const logControlSliderAdjustedEvent = (
      sliderKey: ControlSliderKey,
      sliderValue: number
    ) => {
      logWebUserEvent({
        actionName: 'ControlSliderAdjusted',
        context: {
          sliderType: sliderKey,
          value: sliderValue,
          createVersion: CREATE_VERSION,
        },
      });
    };

    const hasChangedValues =
      sliders.weirdness_constraint !== DEFAULT_CREATE_CONTROL_VALUE ||
      sliders.style_weight !== DEFAULT_CREATE_CONTROL_VALUE ||
      sliders.audio_weight !== DEFAULT_AUDIO_WEIGHT_VALUE;

    return (
      <div className='h-auto rounded-[20px] bg-background-secondary p-2'>
        <div className='flex flex-1 flex-row items-center p-2'>
          <span className='flex items-center font-medium'>
            Advanced Options
            <span className='ml-2 rounded-md bg-accent-pink px-1 py-0.5 text-xs font-medium text-foreground-primary-on-dark'>
              NEW
            </span>
            {hasChangedValues && (
              <Button
                size={ButtonSize.Mini}
                className='ml-2 text-xs'
                shape={ButtonShape.Pill}
                onClick={onResetSliders}
                icon={EditUndoIcon}
              />
            )}
          </span>
          <div className='flex flex-1 flex-row-reverse'>
            <Button
              size={ButtonSize.Mini}
              icon={!isOpen ? CaretDownIcon : CaretUpIcon}
              className='transition-transform duration-500 ease-in-out'
              shape={ButtonShape.Pill}
              onClick={() => {
                onOpenChange(!isOpen);
              }}
            />
          </div>
        </div>
        <div
          className={clsx(
            'flex h-auto flex-col gap-2 overflow-hidden transition-all duration-200 ease-in-out',
            {
              'py-2': isOpen,
              'max-h-0': !isOpen,
            }
          )}
        >
          {withExcludeStyles && onChangeNegativeTags ? (
            <div className='relative h-auto w-auto'>
              <TextInput
                type='text'
                value={negativeTags}
                className='h-12 w-full rounded-[10px] border border-white/10 bg-background-primary py-4 pl-10 outline-none'
                maxLength={getTagsMaxLengthForModel(modelName)}
                placeholder='Exclude styles'
                readOnly={
                  !isFeatureEnabledForPlan(session, PlanFeature.NegativeTags)
                }
                onClick={() => {
                  if (
                    !isFeatureEnabledForPlan(session, PlanFeature.NegativeTags)
                  ) {
                    menus.setCurrentUpsellFeature(FeatureKey.EXCLUDE_STYLES);
                    menus.openModal(ModalTypes.UPSELL_MODAL);
                  }
                }}
                onChange={(e) => {
                  onChangeNegativeTags(e.target.value);
                }}
              />
              <MusicSlashIcon className='absolute top-4 left-4' />
            </div>
          ) : null}
          {session.flags?.['vocal-gender-toggle'] &&
            createV2.activeLyricsMode !== 'instrumental' && (
              <div className='flex flex-1 items-center justify-between rounded-[10px] bg-background-primary px-4 py-1.5'>
                <span className={'text-sm text-foreground-secondary'}>
                  Vocal Gender
                </span>
                <div className='flex flex-row gap-8'>
                  <Button
                    shape={ButtonShape.Pill}
                    className={twMerge(
                      'border-none! px-3 py-1.5 text-sm font-medium before:bg-transparent!',
                      createV2.vocalGender === 'm'
                        ? 'rounded-lg bg-background-tertiary text-foreground-primary'
                        : 'bg-transparent text-foreground-primary/30 hover:text-foreground-primary'
                    )}
                    onClick={() => {
                      if (createV2.vocalGender === 'm') {
                        createV2.setVocalGender(null);
                      } else {
                        createV2.setVocalGender('m');
                      }
                    }}
                  >
                    Male
                  </Button>
                  <Button
                    shape={ButtonShape.Pill}
                    className={twMerge(
                      'border-none! px-3 py-1.5 text-sm font-medium before:bg-transparent!',
                      createV2.vocalGender === 'f'
                        ? 'rounded-lg bg-background-tertiary text-foreground-primary'
                        : 'bg-transparent text-foreground-primary/30 hover:text-foreground-primary'
                    )}
                    onClick={() => {
                      if (createV2.vocalGender === 'f') {
                        createV2.setVocalGender(null);
                      } else {
                        createV2.setVocalGender('f');
                      }
                    }}
                  >
                    Female
                  </Button>
                </div>
              </div>
            )}
          {!isSubscriber(session) &&
          !modelSupportsFeature(
            modelName,
            session.billingModels,
            'create_control_sliders'
          ) ? (
            <>
              <FakeSlider
                label='Weirdness'
                tooltip='Unlock Advanced Sliders with Pro'
              />
              <FakeSlider
                label='Style Influence'
                tooltip='Unlock Advanced Sliders with Pro'
              />
            </>
          ) : null}
          {modelSupportsFeature(
            modelName,
            session.billingModels,
            'create_control_sliders'
          ) ? (
            <>
              <SimpleSlider
                label='Weirdness'
                vertical
                value={sliders.weirdness_constraint}
                onChange={(value) => {
                  onSliderValueChanged(
                    'weirdness_constraint' satisfies ControlSliderKey,
                    value
                  );
                }}
                onChangeEnd={(value) => {
                  logControlSliderAdjustedEvent(
                    'weirdness_constraint' satisfies ControlSliderKey,
                    value
                  );
                }}
                tooltips={SLIDER_VALUE_TOOLTIPS.weirdness_constraint}
                infoTooltip={SLIDER_INFO_TOOLTIPS.weirdness_constraint}
              />
              <SimpleSlider
                label='Style Influence'
                vertical
                value={sliders.style_weight}
                onChange={(value) => {
                  onSliderValueChanged(
                    'style_weight' satisfies ControlSliderKey,
                    value
                  );
                }}
                onChangeEnd={(value) => {
                  logControlSliderAdjustedEvent(
                    'style_weight' satisfies ControlSliderKey,
                    value
                  );
                }}
                tooltips={SLIDER_VALUE_TOOLTIPS.style_weight}
                infoTooltip={SLIDER_INFO_TOOLTIPS.style_weight}
              />
              {hasAudioCondition ? (
                <SimpleSlider
                  label='Audio Influence'
                  vertical
                  value={sliders.audio_weight}
                  onChange={(value) => {
                    onSliderValueChanged(
                      'audio_weight' satisfies ControlSliderKey,
                      value
                    );
                  }}
                  onChangeEnd={(value) => {
                    logControlSliderAdjustedEvent(
                      'audio_weight' satisfies ControlSliderKey,
                      value
                    );
                  }}
                  defaultValue={DEFAULT_AUDIO_WEIGHT_VALUE}
                  tooltips={SLIDER_VALUE_TOOLTIPS.audio_weight}
                  infoTooltip={SLIDER_INFO_TOOLTIPS.audio_weight}
                />
              ) : null}
            </>
          ) : null}
        </div>
      </div>
    );
  }
);
