/* eslint jsx-a11y/click-events-have-key-events: warn */

/* eslint jsx-a11y/no-static-element-interactions: warn */

/* eslint jsx-a11y/label-has-associated-control: warn */
import { useStatsigClient } from '@statsig/react-bindings';
import { useMutation, useQuery } from '@tanstack/react-query';
import { makeAutoObservable } from 'mobx';
import { observer } from 'mobx-react-lite';
import React, { useCallback, useEffect, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import {
  CreateIcon,
  PauseIcon,
  PlayIcon,
  SlidersIcon,
  UserGroupIcon,
} from '@/icons/generated';
import { useApiClient } from '@/lib/apiClient';
import logWebUserEvent from '@/logging/logWebUserEvent';
import {
  USERNAME_VALIDATION_REGEX,
  curatedStyles,
  preferredStyles,
} from '@/utils/constants';

import Button, { ButtonSize, ButtonVariant } from '../button/Button';
import Modal from './Modal';

interface WelcomeModalProps {
  isOpen: boolean;
  onClose: () => void;
  reclaim?: boolean;
}

export type WelcomePage =
  | 'welcome'
  | 'profile'
  | 'birthday'
  | 'preferences'
  | 'survey';

const getPageTitle = (page: WelcomePage): string => {
  switch (page) {
    case 'welcome':
      return 'Welcome to Suno';
    case 'profile':
      return 'Complete your Suno profile';
    case 'birthday':
      return "When's your birthday?";
    case 'preferences':
      return 'What genres are you into?';
    case 'survey':
      return 'Tell us about your experience level';
    default:
      return 'Welcome';
  }
};

const getPageSubtitle = (page: WelcomePage): string | undefined => {
  switch (page) {
    case 'birthday':
      return "We'll arrange something special for your b-day";
    case 'preferences':
      return 'This will help us tailor our taste for you';
    case 'survey':
      return 'Help us improve your experience';
    default:
      return '';
  }
};
// Create a mapping between WelcomePage enum values and numeric indices
const PAGE_MAPPING: Record<WelcomePage, number> = {
  welcome: 1,
  preferences: 2,
  profile: 3,
  birthday: 4,
  survey: 5,
};

// Function to convert WelcomePage to number
const pageToNumber = (page: WelcomePage): number => {
  return PAGE_MAPPING[page] || 1; // Default to 1 if page not found
};

// Function to convert number to WelcomePage
const numberToPage = (pageNumber: number): WelcomePage => {
  const pages = Object.entries(PAGE_MAPPING) as [WelcomePage, number][];
  const page = pages.find(([, value]) => value === pageNumber)?.[0];
  return page || 'preferences'; // Default to 'preferences' if number not found
};

const WelcomeModal: React.FC<WelcomeModalProps> = observer(
  ({ isOpen, onClose, reclaim = false }) => {
    const [currentPage, setCurrentPage] = useState<WelcomePage>('welcome');
    const [welcomeImageLoaded, setWelcomeImageLoaded] = useState(false);
    const { library, session } = useStores();
    const [displayName, setDisplayName] = useState(
      session.user?.display_name || ''
    );
    const [handle, setHandle] = useState(session.user?.handle || '');
    const [profileDescription, setProfileDescription] = useState(
      session.user?.profile_description || ''
    );
    const [errors, setErrors] = useState<{
      display_name?: string;
      handle?: string;
      profile_description?: string;
    }>({});
    const [birthday, setBirthday] = useState('');
    const [selectedStyles, setSelectedStyles] = useState<string[]>([]);
    const [month, setMonth] = useState<string>('');
    const [day, setDay] = useState<string>('');
    const [year, setYear] = useState<string>('');
    const [birthdayError, setBirthdayError] = useState<string>('');
    const [maxPage, setMaxPage] = useState<number>(1);

    // Survey-related state
    const [surveyResponse, setSurveyResponse] = useState<string[]>([]);
    const [surveyError, setSurveyError] = useState<string>('');

    // API client for survey operations
    const apiClient = useApiClient();

    // Fetch the specific survey question from welcome_modal group
    const { data: surveyQuestionsData } = useQuery({
      queryKey: ['survey', 'questions', 'welcome_modal'],
      queryFn: async () => {
        const { data, error } = await apiClient.GET(
          '/api/survey/survey-questions/{group_id}',
          {
            params: { path: { group_id: 'welcome_modal' } },
          }
        );
        if (error) throw error;
        return data;
      },
    });

    // Get the first question from welcome_modal group
    const surveyQuestion = surveyQuestionsData?.questions?.[0];

    // Survey response submission mutation
    const surveyMutation = useMutation({
      mutationFn: async (response: string[]) => {
        if (!surveyQuestion) return;
        const { data, error } = await apiClient.POST(
          '/api/survey/survey-responses',
          {
            body: {
              question_id: surveyQuestion.id,
              response: response,
            },
          }
        );
        if (error) throw error;
        return data;
      },
      onSuccess: () => {
        setSurveyError('');
      },
      onError: (error: any) => {
        console.error('Survey submission error:', error);
        setSurveyError('Failed to submit survey response');
      },
    });

    const nextLabel = currentPage === 'survey' ? 'Done' : 'Next';

    const totalSteps = 5;

    useEffect(() => {
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalViewed'
          : 'WelcomeModalViewed',
      });
    }, [reclaim]);

    useEffect(() => {
      const pageNumber = pageToNumber(currentPage);
      if (pageNumber > maxPage) {
        setMaxPage(pageNumber);
      }
    }, [currentPage]);

    useEffect(() => {
      if (isOpen) {
        // Preload images
        const imagesToPreload = ['https://cdn-o.suno.com/welcome.png'];

        imagesToPreload.forEach((src) => {
          const img = new Image();
          img.src = src;
        });

        // Existing initialization code
        setDisplayName(session.user?.display_name || '');
        setHandle(session.user?.handle || '');
        setProfileDescription(session.user?.profile_description || '');
        setErrors({});

        const initializeData = async () => {
          await Promise.all([
            session.getUserConfig(),
            (async () => {
              const { data } = await library.apiClient.GET('/api/user/me');
              if (data?.birthday) {
                setBirthday(data.birthday);
              }
            })(),
          ]);
        };

        initializeData();
      }
    }, [isOpen, session.user, library.apiClient]);

    // Track page views when currentPage changes
    useEffect(() => {
      if (isOpen) {
        logWebUserEvent({
          actionName: reclaim
            ? 'CompleteProfileModalPageViewed'
            : 'WelcomeModalPageViewed',
          context: {
            page: currentPage,
          },
        });
      }
    }, [currentPage, isOpen, reclaim]);

    useEffect(() => {
      validateDate();
    }, [month, day, year]);

    // Wrap onClose to track closing events
    const handleClose = (method: 'skip' | 'close' | 'complete') => {
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalClosed'
          : 'WelcomeModalClosed',
        context: {
          closedOnPage: currentPage,
          method: method,
        },
      });
      onClose();
    };

    const handleStyleTagAdd = (tagName: string) => {
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalStyleTagAdded'
          : 'WelcomeModalStyleTagAdded',
        context: {
          tagName,
        },
      });
    };

    const handleStyleTagRemove = (tagName: string) => {
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalStyleTagRemoved'
          : 'WelcomeModalStyleTagRemoved',
        context: {
          tagName,
        },
      });
    };

    const handleStyleTagsSubmit = (tags: string[]) => {
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalStyleTagsSubmitted'
          : 'WelcomeModalStyleTagsSubmitted',
        context: {
          tags,
        },
      });
    };

    if (!isOpen) return null;

    const handleSubmit = async () => {
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalProfileSubmitted'
          : 'WelcomeModalProfileSubmitted',
        context: {
          displayName,
          handle,
          profileDescription: profileDescription || null,
        },
      });

      const response = await library.apiClient.POST('/api/profiles/', {
        body: {
          handle: handle,
          display_name: displayName,
          profile_description: profileDescription,
        },
      });

      if (response.error) {
        const newErrors = (response as any).error;
        setErrors({
          ...errors,
          ...newErrors,
        });
      } else {
        session.user.display_name = displayName;
        session.user.handle = handle;
        session.user.profile_description = profileDescription;
        setCurrentPage('birthday');
      }
    };

    const handleStyleSubmit = async (styles: string[]) => {
      try {
        await session.apiClient.POST('/api/user/update_user_config/', {
          body: {
            preferred_tags: styles,
          },
        });
        session.preferredTags = styles;
        handleStyleTagsSubmit(styles);
        setCurrentPage('profile');
      } catch (error) {
        console.error('Failed to save preferences:', error);
        // You might want to show an error toast here
      }
    };

    const formatDateForApi = (): string => {
      if (!month || !day || !year) return '';

      const monthPadded = month.padStart(2, '0');
      const dayPadded = day.padStart(2, '0');
      return `${year}-${monthPadded}-${dayPadded}`;
    };

    const validateDate = (): boolean => {
      // If all fields are empty, it's valid (birthday is optional)
      if (!month && !day && !year) return true;

      // If any field is provided, all fields must be provided
      if (!month || !day || !year) {
        setBirthdayError('Please complete all date fields');
        return false;
      }

      const monthNum = parseInt(month, 10);
      const dayNum = parseInt(day, 10);
      const yearNum = parseInt(year, 10);

      // Check if the date is valid
      const date = new Date(yearNum, monthNum - 1, dayNum);
      if (
        date.getMonth() !== monthNum - 1 || // Check if month rolled over (invalid day for month)
        date.getDate() !== dayNum ||
        date.getFullYear() !== yearNum ||
        yearNum < 1850 ||
        date > new Date() // Future date
      ) {
        setBirthdayError('Please enter a valid date');
        return false;
      }

      setBirthdayError('');
      return true;
    };

    const handleBirthdaySubmit = async () => {
      if (!validateDate()) return { error: birthdayError };

      const formattedDate = formatDateForApi();

      if (formattedDate) {
        try {
          logWebUserEvent({
            actionName: reclaim
              ? 'CompleteProfileModalBirthdaySubmitted'
              : 'WelcomeModalBirthdaySubmitted',
            context: {
              birthday: formattedDate,
            },
          });

          const response = await library.apiClient.POST('/api/profiles/', {
            body: {
              birth_date: formattedDate,
              display_name: session.user?.display_name,
              handle: session.user?.handle,
              profile_description: session.user?.profile_description,
            },
          });

          if (response.error) {
            return { error: 'Failed to update birthday. Please try again.' };
          }

          if (session.user) {
            session.user.birthday = formattedDate;
          }
          setBirthday(formattedDate);
          setCurrentPage('survey');
          return { success: true };
        } catch (error) {
          console.error('Failed to submit birthday:', error);
          return { error: 'Failed to update birthday. Please try again.' };
        }
      } else {
        // If no date was provided, just move to the next step
        setCurrentPage('survey');
        return { success: true };
      }
    };

    const handleSurveySubmit = async () => {
      if (!surveyQuestion) {
        // If no survey question is loaded, just close
        handleClose('complete');
        return { success: true };
      }

      // Skip if no response provided (survey is optional)
      if (surveyResponse.length === 0) {
        handleClose('complete');
        return { success: true };
      }

      try {
        await surveyMutation.mutateAsync(surveyResponse);

        logWebUserEvent({
          actionName: reclaim
            ? 'CompleteProfileModalSurveySubmitted'
            : 'WelcomeModalSurveySubmitted',
          context: {
            surveyResponse,
          },
        });

        handleClose('complete');
        return { success: true };
      } catch (error) {
        console.error('Failed to submit survey:', error);
        setSurveyError('Failed to submit survey response');
        return { error: 'Failed to submit survey response. Please try again.' };
      }
    };

    const getNextPageFunction = (currentPage: WelcomePage) => {
      switch (currentPage) {
        case 'welcome':
          return () => {
            setCurrentPage('preferences');
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalNextClicked'
                : 'WelcomeModalNextClicked',
              context: { fromPage: 'welcome', toPage: 'preferences' },
            });
          };
        case 'preferences':
          return () => {
            handleStyleSubmit(selectedStyles);
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalNextClicked'
                : 'WelcomeModalNextClicked',
              context: { fromPage: 'preferences', toPage: 'profile' },
            });
          };
        case 'profile':
          return () => {
            handleSubmit();
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalNextClicked'
                : 'WelcomeModalNextClicked',
              context: { fromPage: 'profile', toPage: 'birthday' },
            });
          };
        case 'birthday':
          return () => {
            handleBirthdaySubmit();
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalNextClicked'
                : 'WelcomeModalNextClicked',
              context: { fromPage: 'birthday', toPage: 'survey' },
            });
          };
        case 'survey':
          return () => {
            handleSurveySubmit();
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalNextClicked'
                : 'WelcomeModalNextClicked',
              context: { fromPage: 'survey', toPage: 'survey' },
            });
          };
        default:
          return () => handleClose('complete');
      }
    };

    const getSkipFunction = (currentPage: WelcomePage) => {
      switch (currentPage) {
        case 'welcome':
          return () => {
            setCurrentPage('preferences');
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalSkipClicked'
                : 'WelcomeModalSkipClicked',
              context: { fromPage: 'welcome', toPage: 'preferences' },
            });
          };
        case 'preferences':
          return () => {
            setCurrentPage('profile');
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalSkipClicked'
                : 'WelcomeModalSkipClicked',
              context: { fromPage: 'preferences', toPage: 'profile' },
            });
          };
        case 'profile':
          return () => {
            setCurrentPage('birthday');
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalSkipClicked'
                : 'WelcomeModalSkipClicked',
              context: { fromPage: 'profile', toPage: 'birthday' },
            });
          };
        case 'birthday':
          return () => {
            setCurrentPage('survey');
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalSkipClicked'
                : 'WelcomeModalSkipClicked',
              context: { fromPage: 'birthday', toPage: 'survey' },
            });
          };
        case 'survey':
          return () => {
            handleClose('skip');
            logWebUserEvent({
              actionName: reclaim
                ? 'CompleteProfileModalSkipClicked'
                : 'WelcomeModalSkipClicked',
              context: { fromPage: 'survey', toPage: 'survey' },
            });
          };
        default:
          return () => handleClose('skip');
      }
    };

    const renderPage = () => {
      switch (currentPage) {
        case 'welcome':
          return (
            <WelcomePage
              setWelcomeImageLoaded={setWelcomeImageLoaded}
              welcomeImageLoaded={welcomeImageLoaded}
            />
          );
        case 'preferences':
          return (
            <PreferencesPage
              onStyleTagAdd={handleStyleTagAdd}
              onStyleTagRemove={handleStyleTagRemove}
              selectedStyles={selectedStyles}
              setSelectedStyles={setSelectedStyles}
              reclaim={reclaim}
            />
          );

        case 'profile':
          return (
            <ProfilePage
              displayName={displayName}
              handle={handle}
              errors={errors}
              setDisplayName={setDisplayName}
              setHandle={setHandle}
              setErrors={setErrors}
            />
          );
        case 'birthday':
          return (
            <BirthdayPage
              initialBirthday={birthday}
              month={month}
              setMonth={setMonth}
              day={day}
              setDay={setDay}
              year={year}
              setYear={setYear}
              error={birthdayError}
              setError={setBirthdayError}
            />
          );
        case 'survey':
          return (
            <SurveyPage
              question={surveyQuestion}
              response={surveyResponse}
              setResponse={setSurveyResponse}
              error={surveyError}
              setError={setSurveyError}
            />
          );
        default:
          return null;
      }
    };

    return (
      <Modal
        title={getPageTitle(currentPage)}
        onClose={() => handleClose('close')}
        titleClassName={`${
          currentPage === 'welcome'
            ? 'text-[36px] whitespace-pre'
            : 'text-[28px] whitespace-normal md:whitespace-pre'
        } font-normal font-light pt-[10px] leading-[32px] tracking-[-0.56px] ${
          currentPage === 'birthday'
            ? 'max-w-[250px] xs:max-w-[343px]'
            : 'max-w-[200px] xs:max-w-[343px]'
        }`}
        titleWrapperClasses='p-6 pb-0 relative z-10'
        subtitle={getPageSubtitle(currentPage)}
        subtitleClassName='text-sm'
        subtitleWrapperClasses='px-6 pb-[4px] relative z-10'
        wrapperClasses='h-[calc(100%-90px)] overflow-hidden relative z-10'
        contentWrapperClasses='bg-[url("https://cdn-o.suno.com/aura-hero-v2.jpg")]! overflow-hidden bg-cover! bg-top! relative md:h-[calc(100%-100px)] max-h-[657px]'
        closeButtonClasses='absolute right-[10px] top-[10px] h-[40px] w-[40px] color-white z-20 overflow-hidden p-0 rounded-[100px] bg-[rgba(255,255,255,0.06)] backdrop-blur-lg'
        withAuraBackground={false}
        disablePadding={true}
        withHorizontalPadding={true}
        disableOutsideClick={true}
      >
        {/* Gradient overlay */}
        <div className='absolute inset-0 z-1 h-full bg-linear-to-b from-transparent to-black to-[50.68%]'></div>

        {/* Content */}
        <div className='relative z-10 flex h-full w-full flex-col'>
          <div className='custom-scrollbar-semitransparent flex w-full flex-1 grow items-center justify-center overflow-auto'>
            {renderPage()}
          </div>
          <div className='mt-auto p-6'>
            <NavigationButtons
              page={pageToNumber(currentPage)}
              onNext={getNextPageFunction(currentPage)}
              onSkip={getSkipFunction(currentPage)}
              nextLabel={nextLabel}
              showSkip={true}
              disableNext={
                currentPage === 'profile' &&
                (!validateDisplayName(displayName) || !validateHandle(handle))
              }
              onSetPage={(page: number) => {
                setCurrentPage(numberToPage(page));
                logWebUserEvent({
                  actionName: reclaim
                    ? 'CompleteProfileModalProgressBarClicked'
                    : 'WelcomeModalProgressBarClicked',
                  context: {
                    fromPage: currentPage,
                    toPage: numberToPage(page),
                  },
                });
              }}
              totalSteps={totalSteps}
              maxPage={maxPage}
            />
          </div>
        </div>
      </Modal>
    );
  }
);

interface ProfilePageProps {
  displayName: string;
  handle: string;
  errors: {
    display_name?: string;
    handle?: string;
    profile_description?: string;
  };
  setDisplayName: (value: string) => void;
  setHandle: (value: string) => void;
  setErrors: (errors: any) => void;
}

const ProfilePage: React.FC<ProfilePageProps> = ({
  displayName,
  handle,
  errors,
  setDisplayName,
  setHandle,
  setErrors,
}) => (
  <div className='w-full'>
    <div className='px-6'>
      <div>
        <div className='mt-[18px] mb-[20px]'>
          <div className='mb-[10px] flex items-center justify-between'>
            <label className='text-[16px] leading-normal font-medium'>
              Username *
            </label>
            {errors.handle && (
              <p className='text-[12px] font-medium text-[#FF5757]'>
                {errors.handle}
              </p>
            )}
          </div>
          <div className='relative'>
            <span className='pointer-events-none absolute top-1/2 left-[20px] -translate-y-1/2 text-foreground-secondary'>
              @
            </span>
            <input
              type='text'
              className={`focus:border-0.5 placeholder-opacity-70 w-full rounded-lg border bg-transparent py-[16.5px] pr-[20px] pl-[35px] text-foreground-primary placeholder-foreground-secondary focus:border focus:shadow-[0_0_0_0.5px_accent-brand] focus:outline-none ${
                errors.handle
                  ? 'border-[#FF5757] focus:border-[#FF5757] focus:shadow-[0_0_0_0.5px_var(--color-accent-pink)]'
                  : 'border border-[rgba(255,255,255,0.30)] focus:border-accent-brand'
              }`}
              value={handle}
              maxLength={40}
              placeholder='username'
              onChange={(e) => {
                setHandle(e.target.value);
                setErrors({ ...errors, handle: undefined });
              }}
            />
          </div>
        </div>
        <div className='mb-[20px]'>
          <div className='mb-[10px] flex items-center justify-between'>
            <label className='text-[16px] leading-normal font-medium'>
              Display Name *
            </label>
            {errors.display_name && (
              <p className='text-[12px] font-medium text-[#FF5757]'>
                {errors.display_name}
              </p>
            )}
          </div>
          <input
            type='text'
            className={`focus:border-0.5 placeholder-opacity-70 w-full rounded-lg border bg-transparent px-[20px] py-[16.5px] text-foreground-primary placeholder-foreground-secondary focus:border focus:shadow-[0_0_0_0.5px_accent-brand] focus:outline-none ${
              errors.display_name
                ? 'border-accent-pink focus:border-accent-pink focus:shadow-[0_0_0_0.5px_var(--color-accent-pink)]'
                : 'border-[rgba(255,255,255,0.30)]focus:border-accent-brand border'
            }`}
            value={displayName}
            maxLength={40}
            placeholder='Display Name'
            onChange={(e) => {
              setDisplayName(e.target.value);
              setErrors({ ...errors, display_name: undefined });
            }}
          />
        </div>
      </div>
    </div>
  </div>
);

interface BirthdayPageProps {
  initialBirthday?: string;
  month: string;
  setMonth: (value: string) => void;
  day: string;
  setDay: (value: string) => void;
  year: string;
  setYear: (value: string) => void;
  error: string;
  setError: (value: string) => void;
}

const BirthdayPage: React.FC<BirthdayPageProps> = ({
  initialBirthday = '',
  month,
  setMonth,
  day,
  setDay,
  year,
  setYear,
  error,
}) => {
  // Initialize month, day, year from initialBirthday if available
  useEffect(() => {
    if (initialBirthday) {
      try {
        const date = new Date(initialBirthday);
        if (date && date.getTime()) {
          setMonth((date.getMonth() + 1).toString());
          setDay(date.getDate().toString());
          setYear(date.getFullYear().toString());
        }
      } catch (e) {
        console.error('Failed to parse initial birthday:', e);
      }
    }
  }, [initialBirthday, setMonth, setDay, setYear]);

  // Generate options for the dropdowns
  const months = Array.from({ length: 12 }, (_, i) => {
    const monthNum = i + 1;
    return {
      value: monthNum.toString(),
      label: new Date(2000, i, 1).toLocaleString('default', { month: 'long' }),
    };
  });

  const days = Array.from({ length: 31 }, (_, i) => {
    const day = i + 1;
    return {
      value: day.toString(),
      label: day.toString(),
    };
  });

  const currentYear = new Date().getFullYear();
  const years = Array.from({ length: currentYear - 1850 + 1 }, (_, i) => {
    const year = currentYear - i;
    return {
      value: year.toString(),
      label: year.toString(),
    };
  });

  return (
    <div className='w-full'>
      <div className='px-6'>
        <div className='mt-[14px] mb-[20px]'>
          <div className='mb-[20px]'>
            <div className='mb-[10px] flex items-center justify-between'>
              <label className='text-[16px] leading-normal font-medium'>
                Birthday
              </label>
              {error && (
                <p className='text-[12px] font-medium text-[#FF5757]'>
                  {error}
                </p>
              )}
            </div>

            <div className='flex gap-4'>
              {/* Month dropdown */}
              <div className='flex-1'>
                <select
                  value={month}
                  onChange={(e) => {
                    setMonth(e.target.value);
                  }}
                  className={`w-full appearance-none rounded-lg border bg-transparent px-[12px] py-[14px] text-foreground-primary focus:outline-none ${
                    error
                      ? 'border-[#FF5757] focus:border-[#FF5757]'
                      : 'border border-[rgba(255,255,255,0.30)] focus:border-accent-brand'
                  }`}
                >
                  <option value='' className='bg-tertiary'>
                    Month
                  </option>
                  {months.map((option) => (
                    <option
                      key={option.value}
                      value={option.value}
                      className='bg-tertiary'
                    >
                      {option.label}
                    </option>
                  ))}
                </select>
              </div>

              {/* Day dropdown */}
              <div className='flex-1'>
                <select
                  value={day}
                  onChange={(e) => {
                    setDay(e.target.value);
                  }}
                  className={`w-full appearance-none rounded-lg border bg-transparent px-[12px] py-[14px] text-foreground-primary focus:outline-none ${
                    error
                      ? 'border-[#FF5757] focus:border-[#FF5757]'
                      : 'border border-[rgba(255,255,255,0.30)] focus:border-accent-brand'
                  }`}
                >
                  <option value='' className='bg-tertiary'>
                    Day
                  </option>
                  {days.map((option) => (
                    <option
                      key={option.value}
                      value={option.value}
                      className='bg-tertiary'
                    >
                      {option.label}
                    </option>
                  ))}
                </select>
              </div>

              {/* Year dropdown */}
              <div className='flex-1'>
                <select
                  value={year}
                  onChange={(e) => {
                    setYear(e.target.value);
                  }}
                  className={`w-full appearance-none rounded-lg border bg-transparent px-[12px] py-[14px] text-foreground-primary focus:outline-none ${
                    error
                      ? 'border-[#FF5757] focus:border-[#FF5757]'
                      : 'border border-[rgba(255,255,255,0.30)] focus:border-accent-brand'
                  }`}
                >
                  <option value='' className='bg-tertiary'>
                    Year
                  </option>
                  {years.map((option) => (
                    <option
                      key={option.value}
                      value={option.value}
                      className='bg-tertiary'
                    >
                      {option.label}
                    </option>
                  ))}
                </select>
              </div>
            </div>

            <p className='mt-[15px] mb-[25px] text-center text-[14px] leading-[20px] font-normal text-[#828180]'>
              🔒 Your birthday is kept private
            </p>
          </div>
        </div>
      </div>
    </div>
  );
};

class AudioPlayer {
  private audio: HTMLAudioElement | null;
  private currentGenre: string | null;
  private isPlaying: boolean;
  private GENRE_AUDIO_MAP: Record<string, { audio_urls: string[] }> = {};

  constructor() {
    // Initialize as null and create the element only when in browser environment
    this.audio = typeof window !== 'undefined' ? new Audio() : null;
    this.currentGenre = null;
    this.isPlaying = false;
    makeAutoObservable(this);
  }

  play(genre: string, reclaim = false) {
    if (typeof window === 'undefined') return;
    if (!this.audio) {
      this.audio = new Audio();
    }

    const genreKey = genre.toLowerCase();
    const audioUrl = this.GENRE_AUDIO_MAP[genreKey]?.audio_urls[0];
    if (!audioUrl) {
      console.error(`No audio URL found for genre: ${genre}`);
      return;
    }
    if (this.isPlaying) {
      this.stop(true, reclaim);
    }
    this.audio.src = audioUrl;
    this.audio.play();
    this.currentGenre = genreKey;
    this.isPlaying = true;
    logWebUserEvent({
      actionName: reclaim
        ? 'CompleteProfileModalStyleTagPlayed'
        : 'WelcomeModalStyleTagPlayed',
      context: {
        tagName: genre,
      },
    });
  }

  stop(autoPause = false, reclaim = false) {
    if (typeof window === 'undefined') return;
    if (!this.audio) {
      this.audio = new Audio();
    }

    if (autoPause) {
      this.audio.pause();
      this.isPlaying = false;
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalStyleTagPaused'
          : 'WelcomeModalStyleTagPaused',
        context: {
          tagName: this.currentGenre || '',
          duration: this.audio?.currentTime || 0,
          method: 'auto-pause',
        },
      });
    } else {
      this.audio.pause();
      this.isPlaying = false;
      logWebUserEvent({
        actionName: reclaim
          ? 'CompleteProfileModalStyleTagPaused'
          : 'WelcomeModalStyleTagPaused',
        context: {
          tagName: this.currentGenre || '',
          duration: this.audio?.currentTime || 0,
          method: 'user-pause',
        },
      });
    }
  }

  hasAudioUrl(genre: string) {
    const genreKey = genre.toLowerCase();
    return this.GENRE_AUDIO_MAP[genreKey]?.audio_urls.length > 0;
  }

  isGenrePlaying(genre: string) {
    const genreKey = genre.toLowerCase();
    return this.currentGenre === genreKey && this.isPlaying;
  }

  setGenreAudioMap(genreAudioMap: Record<string, { audio_urls: string[] }>) {
    Object.keys(genreAudioMap).forEach((key) => {
      const genreKey = key.toLowerCase();
      this.GENRE_AUDIO_MAP[genreKey] = genreAudioMap[key];
    });
  }
}

const audioPlayer = new AudioPlayer();
interface PreferencesPageProps {
  onStyleTagAdd: (tagName: string) => void;
  onStyleTagRemove: (tagName: string) => void;
  selectedStyles: string[];
  setSelectedStyles: React.Dispatch<React.SetStateAction<string[]>>;
  reclaim: boolean;
}

// Move StyleTagButton outside of PreferencesPage to prevent remounts
const StyleTagButton = React.memo(
  observer(
    ({
      style,
      isSelected,
      onStyleClick,
      reclaim,
    }: {
      style: string;
      isSelected: boolean;
      onStyleClick: (style: string) => void;
      reclaim: boolean;
    }) => {
      return (
        <button
          key={style}
          onClick={() => onStyleClick(style)}
          className={`rounded-[54px] px-[12px] py-[8px] text-[18px] backdrop-blur-[27px] transition-colors ${
            isSelected
              ? 'bg-white text-black'
              : 'bg-white/10 text-foreground-primary'
          }`}
        >
          <div className='flex items-center gap-2'>
            {audioPlayer.hasAudioUrl(style) &&
              (!audioPlayer.isGenrePlaying(style) ? (
                <div className='rounded-full bg-white/20 p-1'>
                  <PlayIcon
                    className='h-[18px] w-[18px]'
                    onClick={(e) => {
                      e.stopPropagation();
                      audioPlayer.play(style, reclaim);
                    }}
                  />
                </div>
              ) : (
                <div className='rounded-full bg-white/20 p-1'>
                  <PauseIcon
                    className='h-[18px] w-[18px]'
                    onClick={(e) => {
                      e.stopPropagation();
                      audioPlayer.stop(false, reclaim);
                    }}
                  />
                </div>
              ))}
            {style}
          </div>
        </button>
      );
    }
  )
);

const PreferencesPage: React.FC<PreferencesPageProps> = ({
  onStyleTagAdd,
  onStyleTagRemove,
  selectedStyles,
  setSelectedStyles,
  reclaim,
}) => {
  const { session } = useStores();
  const statsigClient = useStatsigClient();

  const [availableStyles, setAvailableStyles] = useState<string[]>([]);
  const [customInput, setCustomInput] = useState('');
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    return () => {
      audioPlayer.stop(true, reclaim);
    };
  }, []);

  // Load user config and initialize available styles when statsig client is ready
  useEffect(() => {
    const initializeStyles = async () => {
      try {
        // Get priority genres from statsig if available
        const priorityGenresConfig =
          statsigClient.getDynamicConfig('priority-genres');

        const onboardingGenresConfig = statsigClient.getDynamicConfig(
          'onboarding-genre-songs'
        );

        if (onboardingGenresConfig.value) {
          audioPlayer.setGenreAudioMap(
            onboardingGenresConfig.value as Record<
              string,
              { audio_urls: string[] }
            >
          );
        }

        const priorityGenres = priorityGenresConfig.get(
          'genres',
          []
        ) as string[];

        // Get user's preferred tags if they exist
        const userPreferredTags = session.preferredTags || [];
        setSelectedStyles(userPreferredTags);

        // Get the predefined preferred styles, prioritizing statsig genres if available
        const effectivePreferredStyles =
          priorityGenres.length > 0 ? priorityGenres : preferredStyles;

        // Filter out styles the user has already selected
        const predefinedPreferredStyles = effectivePreferredStyles
          .filter((style) => !userPreferredTags.includes(style))
          .sort(() => Math.random() - 0.5); // Randomize these preferred styles

        // Get remaining styles from curatedStyles, excluding both user's tags and predefined preferred styles
        const remainingStyles = curatedStyles
          .filter(
            (style) =>
              !userPreferredTags.includes(style) &&
              !effectivePreferredStyles.includes(style)
          )
          .sort(() => Math.random() - 0.5); // Randomize remaining styles

        // Combine in the desired order: user's tags first, then preferred styles, then remaining styles
        setAvailableStyles([
          ...userPreferredTags,
          ...predefinedPreferredStyles,
          ...remainingStyles,
        ]);
      } catch (error) {
        console.error('Failed to load user preferences:', error);

        // Fallback to default initialization if there's an error
        const userPreferredTags = session.preferredTags || [];
        setSelectedStyles(userPreferredTags);

        setAvailableStyles([
          ...userPreferredTags,
          ...preferredStyles
            .filter((style) => !userPreferredTags.includes(style))
            .sort(() => Math.random() - 0.5),
          ...curatedStyles
            .filter(
              (style) =>
                !userPreferredTags.includes(style) &&
                !preferredStyles.includes(style)
            )
            .sort(() => Math.random() - 0.5),
        ]);
      } finally {
        setIsLoading(false);
      }
    };

    initializeStyles();
  }, [statsigClient, session.userConfigIsLoaded, setSelectedStyles]);

  const handleStyleClick = useCallback(
    (style: string) => {
      setSelectedStyles((prev) => {
        const isRemoving = prev.includes(style);

        // Call side effect callbacks
        if (isRemoving) {
          onStyleTagRemove(style);
        } else {
          onStyleTagAdd(style);
        }

        // Return new state
        return isRemoving ? prev.filter((s) => s !== style) : [...prev, style];
      });
    },
    [onStyleTagAdd, onStyleTagRemove, setSelectedStyles]
  );

  const addNewStyle = (value: string) => {
    const newStyle = value.trim();
    if (!newStyle) return;

    // Always ensure style is in availableStyles (add to top if not present)
    setAvailableStyles((prev) =>
      prev.includes(newStyle)
        ? [newStyle, ...prev.filter((style) => style !== newStyle)]
        : [newStyle, ...prev]
    );

    // Add to selectedStyles if not already selected
    setSelectedStyles((prev) =>
      prev.includes(newStyle) ? prev : [...prev, newStyle]
    );

    onStyleTagAdd(newStyle);
    setCustomInput('');
  };

  const handleCustomInput = (e: React.ChangeEvent<HTMLInputElement>) => {
    const value = e.target.value;
    setCustomInput(value);

    if (value.endsWith(',')) {
      addNewStyle(value.slice(0, -1));
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter' && customInput.trim()) {
      e.preventDefault();
      addNewStyle(customInput);
    }
  };

  if (isLoading) {
    return (
      <div className='flex items-center justify-center p-6'>
        <p>Loading preferences...</p>
      </div>
    );
  }

  return (
    <div className='w-full'>
      <div className='px-6 pt-4 md:pt-0'>
        <div className='custom-scrollbar-semitransparent mb-6 flex max-h-[310px] flex-wrap gap-2 overflow-y-auto'>
          {availableStyles.map((style) => (
            <StyleTagButton
              key={style}
              style={style}
              isSelected={selectedStyles.includes(style)}
              onStyleClick={handleStyleClick}
              reclaim={reclaim}
            />
          ))}
        </div>

        <div className='mb-4'>
          <input
            type='text'
            value={customInput}
            onChange={handleCustomInput}
            onKeyDown={handleKeyDown}
            placeholder='Enter your own genres'
            className='w-full rounded-lg border border-[rgba(255,255,255,0.30)] bg-transparent p-[16px] text-foreground-primary focus:border-accent-brand focus:outline-none'
          />
        </div>
      </div>
    </div>
  );
};

const WelcomePage: React.FC<{
  setWelcomeImageLoaded: (loaded: boolean) => void;
  welcomeImageLoaded: boolean;
}> = ({ setWelcomeImageLoaded, welcomeImageLoaded }) => (
  <div className='h-full w-full'>
    <div className='px-6'>
      <div className='mt-[14px] mb-[20px]'>
        <p className='flex max-w-[346px] items-center text-[16px] leading-[24px] font-normal md:text-[18px]'>
          <span className='mr-[12px] inline-block'>
            <CreateIcon className='h-[20px] w-[20px]' />
          </span>
          Create original music with just a prompt
        </p>
        <p className='mt-[16px] flex max-w-[346px] items-center text-[16px] leading-[24px] font-normal md:text-[18px]'>
          <span className='mr-[12px] inline-block'>
            <SlidersIcon className='h-[20px] w-[20px]' />
          </span>
          Go deep with advanced editing tools
        </p>
        <p className='mt-[16px] flex items-center text-[16px] leading-[24px] font-normal md:text-[18px]'>
          <span className='mr-[12px] inline-block'>
            <UserGroupIcon className='h-[20px] w-[20px]' />
          </span>
          Publish to the community and share your creations
        </p>
        <div className='mt-[36px]'>
          <ImageWithPlaceholder
            src='https://cdn-o.suno.com/welcome.png'
            alt='Like songs illustration'
            onLoad={() => setWelcomeImageLoaded(true)}
            loaded={true || welcomeImageLoaded}
          />
        </div>
      </div>
    </div>
  </div>
);

const validateDisplayName = (displayName: string) => {
  return displayName.length <= 64 && displayName.length >= 1;
};

const validateHandle = (handle: string) => {
  return USERNAME_VALIDATION_REGEX.test(handle);
};

interface ImageWithPlaceholderProps {
  src: string;
  alt?: string;
  className?: string;
  loaded?: boolean;
  onLoad?: () => void;
}

const ImageWithPlaceholder: React.FC<ImageWithPlaceholderProps> = ({
  src,
  alt = '',
  className = '',
  loaded = false,
  onLoad = () => {},
}) => {
  const [isLoaded, setIsLoaded] = useState(loaded);

  return (
    <div className='relative w-full'>
      {/* Black placeholder */}
      {!isLoaded && (
        <div
          className={`w-full ${isLoaded ? '' : 'bg-black'} ${className}`}
          style={{
            height:
              typeof window !== 'undefined' && window.innerWidth < 768
                ? '113px'
                : '155px',
          }}
        />
      )}

      {/* Actual image */}
      <img
        className={`w-full pb-0 transition-opacity duration-300 ${
          isLoaded ? 'opacity-100' : 'opacity-0'
        } ${className}`}
        src={src}
        alt={alt}
        onLoad={() => {
          setIsLoaded(true);
          onLoad();
        }}
      />
    </div>
  );
};

interface NavigationButtonsProps {
  onNext: () => void;
  onSkip?: () => void;
  nextLabel?: string;
  showSkip?: boolean;
  disableNext?: boolean;
  isLoading?: boolean;
  page?: number;
  onSetPage?: (page: number) => void;
  totalSteps?: number;
  maxPage?: number;
}

const NavigationButtons: React.FC<NavigationButtonsProps> = ({
  onNext,
  onSkip,
  nextLabel = 'Next',
  showSkip = true,
  disableNext = false,
  isLoading = false,
  page = 1,
  onSetPage,
  totalSteps = 4,
  maxPage = 1,
}) => (
  <div className='flex items-center justify-between'>
    {/* Dots flush left */}
    <div className='flex items-center gap-2'>
      {[...Array(totalSteps)].map((_, dot) => {
        const dotPage = dot + 1;
        const isAfterCurrentPage = dotPage > maxPage;
        return (
          <div
            key={dotPage}
            onClick={() => !isAfterCurrentPage && onSetPage?.(dotPage)}
            className={`h-[10px] rounded-full bg-white transition-all duration-300 ${
              page === dotPage && totalSteps > 1 ? 'w-[32px]' : 'w-[10px]'
            } ${
              isAfterCurrentPage || totalSteps === 1
                ? 'cursor-default opacity-10'
                : page === dotPage
                  ? 'cursor-pointer opacity-100'
                  : 'cursor-pointer opacity-30'
            }`}
          />
        );
      })}
    </div>

    {/* Button(s) flush right */}
    <div className='flex gap-[24px]'>
      {showSkip && (
        <div
          onClick={onSkip}
          className='cursor-pointer rounded-[100px] py-[15px] text-[18px] leading-[24px] font-medium'
        >
          Skip
        </div>
      )}
      <Button
        size={ButtonSize.Medium}
        variant={ButtonVariant.Aura}
        onClick={onNext}
        disabled={disableNext || isLoading}
        className='rounded-[100px] px-[16px]'
      >
        {isLoading ? 'Loading...' : nextLabel}
      </Button>
    </div>
  </div>
);

// Survey Page Component
interface SurveyPageProps {
  question?: {
    id: string;
    prompt: string;
    type: 'radio' | 'input' | 'textarea' | 'multi';
    options?: string[] | null;
    is_required: boolean;
    order: number;
  };
  response: string[];
  setResponse: (value: string[]) => void;
  error: string;
  setError: (value: string) => void;
}

const SurveyPage: React.FC<SurveyPageProps> = ({
  question,
  response,
  setResponse,
  error,
}) => {
  if (!question) {
    return (
      <div className='w-full px-6'>
        <div className='mt-[14px] mb-[20px]'>
          <p className='text-center text-[16px] leading-normal font-medium'>
            Loading survey question...
          </p>
        </div>
      </div>
    );
  }

  return (
    <div className='w-full'>
      <div className='px-6'>
        <div className='mt-[14px] mb-[20px]'>
          <div className='mb-[20px]'>
            <div className='mb-[10px] flex items-center justify-between'>
              <label className='text-[16px] leading-normal font-medium'>
                {question.prompt}
                {question.is_required && (
                  <span className='ml-1 text-[#FF5757]'>*</span>
                )}
              </label>
              {error && (
                <p className='text-[12px] font-medium text-[#FF5757]'>
                  {error}
                </p>
              )}
            </div>
            {question.options && (
              <div className='space-y-3'>
                {question.options.map((option) => {
                  const isChecked = response.includes(option);
                  return (
                    <label
                      key={option}
                      className='flex cursor-pointer items-center'
                    >
                      <input
                        type='radio'
                        name={question.id}
                        value={option}
                        checked={isChecked}
                        onChange={() => setResponse([option])}
                        className='mr-3 h-4 w-4'
                      />
                      <span className='text-[16px] leading-normal'>
                        {option}
                      </span>
                    </label>
                  );
                })}
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

export default WelcomeModal;
