'use client';

/* eslint jsx-a11y/label-has-associated-control: warn */
import {
  DndContext,
  PointerSensor,
  closestCenter,
  useSensor,
  useSensors,
} from '@dnd-kit/core';
import { restrictToVerticalAxis } from '@dnd-kit/modifiers';
import {
  SortableContext,
  arrayMove,
  useSortable,
  verticalListSortingStrategy,
} from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { useStatsigClient } from '@statsig/react-bindings';
import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import React, { useEffect, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import ImageUploader from '@/components/image/ImageUploader';
import useUploadImageFile from '@/hooks/useUploadImageFile';
import {
  DragIcon,
  InstagramIcon,
  MusicNoteIcon,
  PersonaShapeIcon,
  PinIcon,
  PlaylistIcon,
  SoundcloudIcon,
  SpotifyIcon,
  TwitterXIcon,
  YoutubeIcon,
} from '@/icons/generated';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { PlanFeature } from '@/state/sessionStore';
import { USERNAME_VALIDATION_REGEX } from '@/utils/constants';
import { isFeatureEnabledForPlan } from '@/utils/session';

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

interface ProfileEditModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSuccess?: () => void;
  artistProfileInfo?: any;
  onArtistProfileInfoUpdate?: (updatedInfo: any) => void;
}

interface InputFieldProps {
  label?: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  maxLength?: number;
  error?: string;
  required?: boolean;
  leftAddon?: React.ReactNode;
  className?: string;
}

interface TextAreaFieldProps {
  label?: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  maxLength?: number;
  error?: string;
  required?: boolean;
  className?: string;
  rows?: number;
}

const MAX_GENRES = 5;
const MAX_GENRE_LENGTH = 20;

const InputField: React.FC<InputFieldProps> = ({
  label,
  value,
  onChange,
  placeholder = '',
  maxLength,
  error,
  required = false,
  leftAddon,
  className,
}) => {
  return (
    <div className={clsx('mb-[32px]', className)}>
      <div
        className={clsx('mb-[8px] flex items-center justify-between', {
          hidden: !label?.trim(),
        })}
      >
        <label className='text-[14px] leading-[20px] font-medium'>
          {label}
          {required && '*'}
        </label>
      </div>
      <div
        className={`flex ${leftAddon ? 'items-center' : ''} ${
          error
            ? 'rounded-[16px] border border-[#FF5757] focus:border-[#FF5757] focus:shadow-[0_0_0_0.5px_#FF5757]'
            : ''
        }`}
      >
        {leftAddon && (
          <div className='rounded-l-[16px] bg-background-glass-thin py-[12px] pl-[12px]'>
            {leftAddon}
          </div>
        )}
        <input
          type='text'
          className={`w-full bg-background-glass-thin py-[12px] text-foreground-primary ${leftAddon ? 'rounded-r-[16px] pr-[12px]' : 'rounded-[16px] px-[12px]'} placeholder-opacity-70 placeholder-foreground-secondary focus:outline-none`}
          value={value}
          maxLength={maxLength}
          placeholder={placeholder}
          onChange={(e) => {
            onChange(e.target.value);
          }}
        />
      </div>
      {error && (
        <p className='my-1 text-[12px] font-medium text-[#FF5757]'>{error}</p>
      )}
    </div>
  );
};

const TextAreaField: React.FC<TextAreaFieldProps> = ({
  label,
  value,
  onChange,
  placeholder = '',
  maxLength,
  error,
  required = false,
  className,
  rows = 3,
}) => {
  return (
    <div className={clsx('mb-[20px]', className)}>
      <div
        className={clsx('mb-[8px] flex items-center justify-between', {
          hidden: !label?.trim(),
        })}
      >
        <label className='text-[14px] leading-[20px] font-medium'>
          {label}
          {required && '*'}
        </label>
      </div>
      <div className='relative'>
        <textarea
          className={`placeholder-opacity-70 w-full resize-none rounded-[16px] bg-background-glass-thin px-[12px] py-[12px] text-foreground-primary placeholder-foreground-secondary focus:outline-none ${
            error
              ? 'border-[#FF5757] focus:border-[#FF5757] focus:shadow-[0_0_0_0.5px_#FF5757]'
              : ''
          } ${maxLength ? 'pb-[28px]' : ''}`}
          value={value}
          maxLength={maxLength}
          placeholder={placeholder}
          rows={rows}
          onChange={(e) => {
            onChange(e.target.value);
          }}
        />
        {maxLength && (
          <span className='absolute right-[12px] bottom-[12px] rounded-[4px] px-[4px] text-[12px] text-foreground-inactive'>
            {value.length}/{maxLength}
          </span>
        )}
      </div>
      {error && (
        <p className='text-[12px] font-medium text-[#FF5757]'>{error}</p>
      )}
    </div>
  );
};

// Add this new component for sortable section items
const SortableSectionItem: React.FC<{
  id: string;
  title: string;
  icon?: React.ReactNode;
}> = ({ id, title, icon }) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
  };

  return (
    <div
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      className={clsx(
        'mb-2 flex cursor-grab items-center justify-between rounded-[8px] bg-background-glass-thin p-[4px] active:cursor-grabbing',
        'touch-none select-none',
        {
          'shadow-lg': isDragging,
        }
      )}
    >
      <div className='flex w-full items-center gap-3'>
        <div className='flex-1'>
          <div className='flex items-center gap-1 rounded-[8px] p-[4px] pr-[8px] pl-[4px] text-[14px] font-medium text-foreground-secondary select-none'>
            {icon}
            {title}
          </div>
        </div>
        <div className='flex flex-col gap-1'>
          <DragIcon className='h-[16px] w-[16px] text-foreground-secondary' />
        </div>
      </div>
    </div>
  );
};

// Add validation functions after the existing interfaces
const validateSpotifyUrl = (url: string): boolean => {
  if (!url.trim()) return true; // Empty is valid

  const trimmedUrl = url.trim();

  // Catch malformed protocols first
  if (/^htt[^ps]/.test(trimmedUrl) || /^https?:{2,}\/\//.test(trimmedUrl)) {
    return false;
  }

  const spotifyPattern =
    /^(https?:\/\/)?(www\.)?(open\.spotify\.com|spotify\.com|spti\.fi)(\/.*)?\/?$/i;
  return spotifyPattern.test(trimmedUrl);
};

const validateSoundcloudUrl = (url: string): boolean => {
  if (!url.trim()) return true; // Empty is valid

  const trimmedUrl = url.trim();

  // Catch malformed protocols first
  if (/^htt[^ps]/.test(trimmedUrl) || /^https?:{2,}\/\//.test(trimmedUrl)) {
    return false;
  }

  const soundcloudPattern =
    /^(https?:\/\/)?(www\.)?(soundcloud\.com|snd\.sc)(\/.*)?\/?$/i;
  return soundcloudPattern.test(trimmedUrl);
};

const validateXUrl = (url: string): boolean => {
  if (!url.trim()) return true; // Empty is valid

  const trimmedUrl = url.trim();

  // Catch malformed protocols first
  if (/^htt[^ps]/.test(trimmedUrl) || /^https?:{2,}\/\//.test(trimmedUrl)) {
    return false;
  }

  const xPattern =
    /^(https?:\/\/)?(www\.)?(x\.com|twitter\.com|t\.co)(\/.*)?\/?$/i;
  return xPattern.test(trimmedUrl);
};

const validateInstagramUrl = (url: string): boolean => {
  if (!url.trim()) return true; // Empty is valid

  const trimmedUrl = url.trim();

  // Catch malformed protocols first
  if (/^htt[^ps]/.test(trimmedUrl) || /^https?:{2,}\/\//.test(trimmedUrl)) {
    return false;
  }

  const instagramPattern = /^(https?:\/\/)?(www\.)?instagram\.com(\/.*)?\/?$/i;
  return instagramPattern.test(trimmedUrl);
};

const validateYoutubeUrl = (url: string): boolean => {
  if (!url.trim()) return true; // Empty is valid

  const trimmedUrl = url.trim();

  // Catch malformed protocols first
  if (/^htt[^ps]/.test(trimmedUrl) || /^https?:{2,}\/\//.test(trimmedUrl)) {
    return false;
  }

  const youtubePattern =
    /^(https?:\/\/)?(www\.)?(youtube\.com|youtu\.be)(\/.*)?\/?$/i;
  return youtubePattern.test(trimmedUrl);
};

const ProfileEditModal: React.FC<ProfileEditModalProps> = observer(
  ({
    isOpen,
    onClose,
    onSuccess,
    artistProfileInfo,
    onArtistProfileInfoUpdate,
  }) => {
    const { library, session } = useStores();
    const [displayName, setDisplayName] = useState('');
    const [handle, setHandle] = useState('');
    const [bio, setBio] = useState('');
    const [userInputtedGenres, setUserInputtedGenres] = useState<string[]>([]);
    const [currentGenreInput, setCurrentGenreInput] = useState('');
    const [spotifyLink, setSpotifyLink] = useState('');
    const [soundcloudLink, setSoundcloudLink] = useState('');
    const [xLink, setXLink] = useState('');
    const [instagramLink, setInstagramLink] = useState('');
    const [youtubeLink, setYoutubeLink] = useState('');
    const [displayNameError, setDisplayNameError] = useState<string>('');
    const [handleError, setHandleError] = useState<string>('');
    const [isSubmitting, setIsSubmitting] = useState(false);
    const [imageDataURL, setImageDataURL] = useState<string | null>(null);
    const [imageCoverURL, setImageCoverURL] = useState<string | null>(null);
    const [imageChanged, setImageChanged] = useState(false);
    const [imageCoverChanged, setImageCoverChanged] = useState(false);
    const [initialImageURL, setInitialImageURL] = useState<string | null>(null);
    const [initialImageCoverURL, setInitialImageCoverURL] = useState<
      string | null
    >(null);
    const [isGenerating, setIsGenerating] = useState(false);
    const [editedImagePrompt, setEditedImagePrompt] = useState<string>('');
    const [moderationError, setModerationError] = useState<string>('');

    // Add section ordering state
    const [sectionOrder, setSectionOrder] = useState<string[]>([
      'hooks',
      'pinned_songs',
      'songs',
      'playlists',
      'personas',
    ]);

    const uploadImageFile = useUploadImageFile();

    const statsigClient = useStatsigClient();
    const enableImageUpload = statsigClient.checkGate(
      'enable-frontend-profile-pic-upload'
    );
    const hooksGate = statsigClient.checkGate('artist-profiles-hooks');

    // Add drag and drop sensors
    const sensors = useSensors(
      useSensor(PointerSensor, {
        activationConstraint: {
          distance: 8,
        },
      })
    );

    // Section titles mapping
    const sectionTitles = {
      ...(hooksGate === true
        ? {
            hooks: {
              title: 'Hooks',
              description:
                'Express your creativity and bring your songs to life with short-form music videos',
              icon: (
                <MusicNoteIcon className='h-[16px] w-[16px] text-foreground-secondary' />
              ),
            },
          }
        : {}),
      pinned_songs: {
        title: 'Featured Songs',
        icon: (
          <PinIcon className='h-[16px] w-[16px] text-foreground-secondary' />
        ),
        description: 'Your featured songs displayed prominently',
      },
      songs: {
        title: 'Songs',
        description: 'Your main song collection',
        icon: (
          <MusicNoteIcon className='h-[16px] w-[16px] text-foreground-secondary' />
        ),
      },
      playlists: {
        title: 'Playlists',
        description: 'Your curated song collections',
        icon: (
          <PlaylistIcon className='h-[16px] w-[16px] text-foreground-secondary' />
        ),
      },
      personas: {
        title: 'Personas',
        description: 'Your AI personalities for music creation',
        icon: (
          <PersonaShapeIcon className='h-[16px] w-[16px] text-foreground-secondary' />
        ),
      },
    } as const;

    // Add error states for social links
    const [spotifyLinkError, setSpotifyLinkError] = useState<string>('');
    const [soundcloudLinkError, setSoundcloudLinkError] = useState<string>('');
    const [xLinkError, setXLinkError] = useState<string>('');
    const [instagramLinkError, setInstagramLinkError] = useState<string>('');
    const [youtubeLinkError, setYoutubeLinkError] = useState<string>('');

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

    useEffect(() => {
      if (isOpen) {
        // Initialize with current data including section order
        setDisplayName(session.user?.display_name || '');
        setHandle(session.user?.handle || '');
        setBio(session.user?.profile_description || '');
        setUserInputtedGenres(artistProfileInfo?.user_inputted_genres || []);
        setCurrentGenreInput('');
        setSpotifyLink(artistProfileInfo?.spotify_link || '');
        setSoundcloudLink(artistProfileInfo?.soundcloud_link || '');
        setXLink(artistProfileInfo?.x_link || '');
        setInstagramLink(artistProfileInfo?.instagram_link || '');
        setYoutubeLink(artistProfileInfo?.youtube_link || '');
        const apiOrder = artistProfileInfo?.section_order || [
          'pinned_songs',
          'songs',
          'playlists',
          'personas',
        ];
        const apiOrderHasHooks = apiOrder.includes('hooks');
        const uiOrder =
          hooksGate === true && !apiOrderHasHooks
            ? ['hooks', ...apiOrder]
            : apiOrder;
        setSectionOrder(uiOrder);
        setInitialImageURL(session.user?.avatar_image_url);
        setInitialImageCoverURL(artistProfileInfo?.cover_photo_url);
        setDisplayNameError('');
        setHandleError('');
        setModerationError('');

        // Clear social link errors
        setSpotifyLinkError('');
        setSoundcloudLinkError('');
        setXLinkError('');
        setInstagramLinkError('');
        setYoutubeLinkError('');

        logWebUserEvent(
          {
            actionName: 'ArtistProfileEditModalViewed',
          },
          session
        );
      }
    }, [
      isOpen,
      session.user?.display_name,
      session.user?.handle,
      session.user?.profile_description,
      session.user?.avatar_image_url,
      artistProfileInfo?.location,
      artistProfileInfo?.user_inputted_genres,
      artistProfileInfo?.spotify_link,
      artistProfileInfo?.soundcloud_link,
      artistProfileInfo?.x_link,
      artistProfileInfo?.instagram_link,
      artistProfileInfo?.youtube_link,
      artistProfileInfo?.section_order,
      hooksGate,
    ]);

    // Handle drag end for section reordering
    const handleSectionDragEnd = (event: any) => {
      const { active, over } = event;

      if (active.id !== over.id) {
        setSectionOrder((items) => {
          const oldIndex = items.indexOf(active.id);
          const newIndex = items.indexOf(over.id);
          const newOrder = arrayMove(items, oldIndex, newIndex);

          // Log the reorder event with the final order
          logWebUserEvent(
            {
              actionName: 'ArtistProfileSectionReordered',
              context: {
                newOrder: newOrder,
              },
            },
            session
          );

          return newOrder;
        });
      }
    };

    const handleClose = (
      method: 'close' | 'cancel' | 'outside-click' = 'close'
    ) => {
      logWebUserEvent(
        {
          actionName: 'ArtistProfileEditModalClosed',
          context: {
            method,
          },
        },
        session
      );
      onClose();
    };

    const handleSubmit = async () => {
      logWebUserEvent(
        {
          actionName: 'ArtistProfileEditModalSubmitted',
          context: {
            displayName: displayName.trim(),
            handle: handle.trim(),
            bio: bio.trim(),
            userInputtedGenres: userInputtedGenres,
            spotifyLink: spotifyLink.trim(),
            soundcloudLink: soundcloudLink.trim(),
            xLink: xLink.trim(),
            instagramLink: instagramLink.trim(),
            youtubeLink: youtubeLink.trim(),
            sectionOrder:
              hooksGate === true
                ? sectionOrder
                : ['hooks', ...sectionOrder.filter((s) => s !== 'hooks')],
            hasAvatarImage: !!imageDataURL || !!session.user?.avatar_image_url,
            hasCoverImage:
              !!imageCoverURL || !!artistProfileInfo?.cover_photo_url,
            avatarImageChanged: imageChanged,
            coverImageChanged: imageCoverChanged,
          },
        },
        session
      );

      let hasError = false;

      if (!displayName.trim()) {
        setDisplayNameError('Display name is required');
        hasError = true;
      } else if (displayName.length > 40) {
        setDisplayNameError('Display name must be 40 characters or less');
        hasError = true;
      }

      if (!handle.trim()) {
        setHandleError('Handle is required');
        hasError = true;
      } else if (!validateHandle(handle)) {
        setHandleError(
          'Handle must be 3-40 characters using only letters, numbers and underscores'
        );
        hasError = true;
      }

      // Validate social links
      if (!validateSpotifyUrl(spotifyLink)) {
        setSpotifyLinkError('Please enter a valid Spotify URL');
        hasError = true;
      }
      if (!validateSoundcloudUrl(soundcloudLink)) {
        setSoundcloudLinkError('Please enter a valid SoundCloud URL');
        hasError = true;
      }
      if (!validateXUrl(xLink)) {
        setXLinkError('Please enter a valid X/Twitter URL');
        hasError = true;
      }
      if (!validateInstagramUrl(instagramLink)) {
        setInstagramLinkError('Please enter a valid Instagram URL');
        hasError = true;
      }
      if (!validateYoutubeUrl(youtubeLink)) {
        setYoutubeLinkError('Please enter a valid YouTube URL');
        hasError = true;
      }

      if (hasError) return;

      setIsSubmitting(true);
      setDisplayNameError('');
      setHandleError('');
      setModerationError('');

      let uploadedAvatarS3Id = null;
      if (enableImageUpload) {
        const uploadImage = async (imageDataURL: string | null) => {
          if (!imageDataURL) {
            return null;
          }

          const [header, base64Data] = imageDataURL.split(',');
          const mimeType = header.match(/data:([^;]+)/)?.[1] || 'image/jpeg';
          const binaryString = atob(base64Data);
          const bytes = new Uint8Array(binaryString.length);
          for (let i = 0; i < binaryString.length; i++) {
            bytes[i] = binaryString.charCodeAt(i);
          }
          const blob = new Blob([bytes], { type: mimeType });

          // Generate a proper filename based on the MIME type
          const fileExtension = mimeType.split('/')[1] || 'jpeg';
          const filename = `image_${Date.now()}.${fileExtension}`;

          const uploadImageResult = await uploadImageFile(
            blob,
            'file_upload',
            filename
          );
          if (uploadImageResult?.uploadId) {
            return uploadImageResult.uploadId;
          }
          return null;
        };
        uploadedAvatarS3Id = await uploadImage(imageDataURL);
      }

      try {
        // Build section order payload per plan
        let sectionOrderToSend: string[] = [];
        if (hooksGate !== true) {
          // 1. Gate off: remove hooks from payload
          sectionOrderToSend = sectionOrder.filter((s) => s !== 'hooks');
        } else {
          // Gate on: ensure hooks included
          if (!sectionOrder.includes('hooks')) {
            sectionOrderToSend = ['hooks', ...sectionOrder];
          } else {
            sectionOrderToSend = [...sectionOrder];
          }
        }

        const [profileResponse, infoResponse] = await Promise.all([
          library.apiClient.POST('/api/profiles/', {
            body: {
              display_name: displayName.trim(),
              handle: handle.trim(),
              profile_description: bio.trim() || '',
              ...(enableImageUpload
                ? { avatar_image_s3_id: uploadedAvatarS3Id || null }
                : {
                    avatar_image_url:
                      imageDataURL || session.user?.avatar_image_url,
                  }),
            },
          }),
          library.apiClient.PUT('/api/profiles/info', {
            body: {
              user_inputted_genres: userInputtedGenres,
              spotify_link: spotifyLink.trim() || null,
              soundcloud_link: soundcloudLink.trim() || null,
              x_link: xLink.trim() || null,
              instagram_link: instagramLink.trim() || null,
              youtube_link: youtubeLink.trim() || null,
              section_order: sectionOrderToSend,
              ...(imageCoverChanged
                ? { cover_photo_url: imageCoverURL || null }
                : {}),
            },
          }),
        ]);

        // Check for moderation errors
        const isProfileModerationError =
          profileResponse.error &&
          ((profileResponse as any).error.display_name?.includes(
            'Moderation error'
          ) ||
            (profileResponse as any).error.handle?.includes(
              'Moderation error'
            ) ||
            (profileResponse as any).error.profile_description?.includes(
              'Moderation error'
            ) ||
            (profileResponse as any).error.avatar_image_url?.includes(
              'Moderation error'
            ));

        const isInfoModerationError =
          infoResponse.data &&
          (infoResponse as any).data.success === false &&
          (infoResponse as any).data.message?.includes('Moderation error');

        if (isProfileModerationError || isInfoModerationError) {
          setModerationError(
            'Your profile information did not pass moderation, please update and try again.'
          );
          return;
        }

        // Update the parent component's artist profile info
        if (onArtistProfileInfoUpdate) {
          onArtistProfileInfoUpdate({
            ...artistProfileInfo,
            user_inputted_genres: userInputtedGenres,
            spotify_link: spotifyLink.trim() || null,
            soundcloud_link: soundcloudLink.trim() || null,
            x_link: xLink.trim() || null,
            instagram_link: instagramLink.trim() || null,
            youtube_link: youtubeLink.trim() || null,
            section_order: sectionOrderToSend,
            ...(imageCoverChanged
              ? { cover_photo_url: imageCoverURL || null }
              : {}),
          });
        }

        if (profileResponse.error) {
          if ((profileResponse as any).error.display_name) {
            setDisplayNameError((profileResponse as any).error.display_name);
          }
          if ((profileResponse as any).error.handle) {
            setHandleError((profileResponse as any).error.handle);
          }
          if (
            !(profileResponse as any).error.display_name &&
            !(profileResponse as any).error.handle
          ) {
            setModerationError('Failed to update profile. Please try again.');
          }
        } else {
          // Update the session with the new display name, handle, bio and avatar
          if (session.user) {
            session.user.display_name = displayName.trim();
            session.user.handle = handle.trim();
            session.user.profile_description = bio.trim() || null;
            if (imageChanged && imageDataURL) {
              session.user.avatar_image_url = imageDataURL;
            }
          }

          onSuccess?.();
          handleClose();
        }
      } catch (error) {
        console.error('Failed to update profile:', error);

        // Check if it's a 413 Content Too Large error (image dimensions/size issue)
        if ((error as any)?.status === 413) {
          setModerationError(
            'Image is too large. Please use a smaller image or reduce dimensions.'
          );
        } else {
          // TODO: Change this to a more specific error message once the 413 error is fixed
          setModerationError(
            'Image is too large. Please use a smaller image or reduce dimensions.'
          );
        }
      } finally {
        setIsSubmitting(false);
      }
    };

    // Check if any social links are invalid
    const hasSocialLinkErrors = () => {
      return (
        !validateSpotifyUrl(spotifyLink) ||
        !validateSoundcloudUrl(soundcloudLink) ||
        !validateXUrl(xLink) ||
        !validateInstagramUrl(instagramLink) ||
        !validateYoutubeUrl(youtubeLink)
      );
    };

    // Add helper functions for genre management
    const addGenre = () => {
      const trimmedGenre = currentGenreInput.trim();
      if (
        trimmedGenre &&
        !userInputtedGenres.includes(trimmedGenre) &&
        userInputtedGenres.length < MAX_GENRES
      ) {
        const newGenres = [...userInputtedGenres, trimmedGenre];
        setUserInputtedGenres(newGenres);
        setCurrentGenreInput('');

        // Log the genre addition
        logWebUserEvent(
          {
            actionName: 'ArtistProfileGenreAdded',
            context: {
              genre: trimmedGenre,
              totalGenres: newGenres.length,
            },
          },
          session
        );
      }
    };

    const removeGenre = (indexToRemove: number) => {
      const genreToRemove = userInputtedGenres[indexToRemove];
      const newGenres = userInputtedGenres.filter(
        (_, index) => index !== indexToRemove
      );
      setUserInputtedGenres(newGenres);

      // Log the genre removal
      logWebUserEvent(
        {
          actionName: 'ArtistProfileGenreRemoved',
          context: {
            genre: genreToRemove,
            totalGenres: newGenres.length,
          },
        },
        session
      );
    };

    const handleGenreKeyPress = (e: React.KeyboardEvent) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        addGenre();
      }
    };

    if (!isOpen) return null;

    const visibleSectionOrder =
      hooksGate === true
        ? sectionOrder
        : sectionOrder.filter((s) => s !== 'hooks');

    return (
      <Modal
        title='Edit Profile'
        onClose={() => handleClose('close')}
        titleClassName='text-[20px] font-normal font-sans font-medium pt-[10px] leading-[24px] max-w-[343px]'
        titleWrapperClasses='p-6 pb-0 relative z-10 block text-center'
        wrapperClasses='h-[calc(100%-90px)] overflow-hidden relative z-10'
        contentWrapperClasses='h-[calc(100%-90px)]'
        closeButtonClasses='absolute right-[10px] top-[10px] h-[40px] w-[40px] color-white z-20 overflow-hidden p-0 rounded-[100px] bg-none'
        withAuraBackground={false}
        disablePadding={true}
        withHorizontalPadding={true}
        disableOutsideClick={false}
      >
        {/* 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'>
            <div className='h-full w-full px-6'>
              <div className='mt-[18px]'>
                <div className='mb-[32px]'>
                  <div className='mb-[8px] flex items-center justify-between'>
                    <label className='text-[14px] leading-[20px] font-medium'>
                      Background image
                    </label>
                  </div>
                  <div className='flex w-full flex-col items-center justify-center gap-[12px]'>
                    <div
                      className={`w-full flex-1 ${!imageCoverURL ? 'overflow-clip rounded-[8px] border border-border-primary' : ''}`}
                    >
                      <ImageUploader
                        initialImageURL={initialImageCoverURL || undefined}
                        onImageChanged={(imageData: string | null) => {
                          const hadImageBefore = !!(
                            imageCoverURL || initialImageCoverURL
                          );

                          if (imageData === null) {
                            // Image was removed
                            if (hadImageBefore) {
                              logWebUserEvent(
                                {
                                  actionName: 'ArtistProfileCoverPhotoRemoved',
                                },
                                session
                              );
                            }
                          } else {
                            // Image was added
                            if (!hadImageBefore) {
                              logWebUserEvent(
                                {
                                  actionName: 'ArtistProfileCoverPhotoAdded',
                                },
                                session
                              );
                            }
                          }

                          setImageCoverURL(imageData);
                          setImageCoverChanged(true);
                        }}
                        className='h-auto w-full border-none'
                        uploaderClassName='border-none'
                        height={160}
                        innerClassName='border-none'
                        style={{
                          width: '100%',
                          height: 160,
                          borderRadius: '12px%',
                        }}
                        paddingX={0}
                        paddingY={0}
                        minScale={1}
                      />
                    </div>
                    <div className='flex-1'>
                      <div className='mb-[4px] text-[14px] leading-[20px] font-medium text-foreground-secondary'>
                        Upload a cover image JPEG, PNG, WEBP, Max 5MB, 1280x740
                        max.
                      </div>
                    </div>
                  </div>
                </div>
                <div className='mb-[32px]'>
                  <div className='mb-[8px] flex items-center justify-between'>
                    <label className='text-[14px] leading-[20px] font-medium'>
                      Profile picture
                    </label>
                  </div>
                  <div className='flex items-center justify-center gap-[12px]'>
                    <div
                      className={
                        !imageDataURL
                          ? 'rounded-[100px] border border-[rgba(255,255,255,0.15)]'
                          : ''
                      }
                    >
                      <ImageUploader
                        initialImageURL={initialImageURL || undefined}
                        onImageChanged={(imageData: string | null) => {
                          const hadImageBefore = !!(
                            imageDataURL || initialImageURL
                          );

                          if (imageData === null) {
                            // Image was removed
                            if (hadImageBefore) {
                              logWebUserEvent(
                                {
                                  actionName: 'ArtistProfileAvatarRemoved',
                                },
                                session
                              );
                            }
                          } else {
                            // Image was added
                            if (!hadImageBefore) {
                              logWebUserEvent(
                                {
                                  actionName: 'ArtistProfileAvatarAdded',
                                },
                                session
                              );
                            }
                          }

                          setImageDataURL(imageData);
                          setImageChanged(true);
                        }}
                        className='h-auto border-none'
                        uploaderClassName='border-none'
                        uploaderIconClassName='w-8 h-10'
                        uploaderTextClassName='hidden'
                        height={104}
                        width={104}
                        style={{
                          width: 104,
                          height: 104,
                          borderRadius: '100%',
                        }}
                        paddingX={0}
                        paddingY={0}
                        minScale={1}
                        buttonContainerClassName='top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2'
                        sliderContainerClassName='inset-x-[30px]'
                      />
                    </div>
                    <div className='flex-1'>
                      <div className='mb-[4px] text-[14px] leading-[20px] font-medium text-foreground-secondary'>
                        Upload an image
                      </div>
                      <div className='text-[12px] text-foreground-inactive'>
                        JPEG, PNG, WEBP, BMP, Max 5MB, 500x500 max.
                      </div>
                    </div>
                  </div>

                  {isFeatureEnabledForPlan(
                    session,
                    PlanFeature.GenerateSongImage
                  ) && (
                    <>
                      <div className='mt-[8px] flex gap-2'>
                        <input
                          type='text'
                          className='placeholder-opacity-70 w-full rounded-[16px] bg-background-glass-thin px-[12px] py-[12px] text-[14px] text-foreground-primary placeholder-foreground-secondary focus:outline-none'
                          placeholder='Prompt Suno to create an image'
                          value={editedImagePrompt}
                          maxLength={200}
                          onChange={(e) => setEditedImagePrompt(e.target.value)}
                        />
                        <Button
                          size={ButtonSize.Small}
                          variant={ButtonVariant.Standard}
                          onClick={async () => {
                            setIsGenerating(true);
                            const { data } = await library.apiClient.POST(
                              '/api/gen/prompt_image/',
                              {
                                body: {
                                  prompt: editedImagePrompt,
                                },
                              }
                            );
                            setIsGenerating(false);
                            if (data) {
                              setInitialImageURL((data as any).image_url);
                            }
                          }}
                          disabled={isGenerating || editedImagePrompt === ''}
                          className='rounded-[100px] py-[12px]'
                        >
                          Create
                        </Button>
                      </div>
                      {isGenerating && (
                        <div className='mt-2 flex flex-row'>
                          <SpinnerSVG className='mr-2' />
                          <span className='text-[14px]'>Creating image...</span>
                        </div>
                      )}
                    </>
                  )}
                </div>

                <InputField
                  label='Display Name'
                  value={displayName}
                  onChange={(value) => {
                    setDisplayName(value);
                    setDisplayNameError('');
                  }}
                  maxLength={40}
                  error={displayNameError}
                  required={false}
                />

                <TextAreaField
                  label='Add a bio'
                  value={bio}
                  onChange={(value) => {
                    setBio(value);
                  }}
                  placeholder='Tell us about yourself...'
                  maxLength={1200}
                  rows={4}
                  required={false}
                />

                <InputField
                  label='Handle'
                  value={handle}
                  onChange={(value) => {
                    setHandle(value);
                    setHandleError('');
                  }}
                  maxLength={40}
                  error={handleError}
                  required={true}
                  leftAddon={<span>@</span>}
                />

                <div className='mb-[32px]'>
                  <div className='mb-[8px] flex items-center justify-between'>
                    <label className='text-[14px] leading-[20px] font-medium'>
                      Genres Override
                    </label>
                  </div>
                  <div className='mb-[8px] text-[12px] text-foreground-secondary'>
                    Add up to {MAX_GENRES} genres to describe your music style.
                    If this is empty, the genres will be inferred from your most
                    popular songs
                  </div>
                  <div className='flex gap-2'>
                    <div className='relative flex-1'>
                      <input
                        type='text'
                        className='w-full rounded-[16px] bg-background-glass-thin px-[12px] py-[12px] pr-[50px] text-foreground-primary placeholder-foreground-secondary/70 focus:outline-none'
                        placeholder='Type a genre...'
                        value={currentGenreInput}
                        maxLength={MAX_GENRE_LENGTH}
                        onChange={(e) => setCurrentGenreInput(e.target.value)}
                        onKeyPress={handleGenreKeyPress}
                        disabled={userInputtedGenres.length >= MAX_GENRES}
                      />
                      <span className='absolute top-1/2 right-[12px] -translate-y-1/2 rounded-[4px] px-[4px] text-[12px] text-foreground-secondary/70'>
                        {currentGenreInput.length}/{MAX_GENRE_LENGTH}
                      </span>
                    </div>
                    <Button
                      size={ButtonSize.Small}
                      variant={ButtonVariant.Standard}
                      onClick={addGenre}
                      disabled={
                        !currentGenreInput.trim() ||
                        userInputtedGenres.includes(currentGenreInput.trim()) ||
                        userInputtedGenres.length >= MAX_GENRES
                      }
                      className='rounded-[16px] px-[16px]'
                    >
                      Add
                    </Button>
                  </div>
                  {userInputtedGenres.length > 0 && (
                    <div className='mt-[12px] flex flex-wrap gap-2'>
                      {userInputtedGenres.map((genre, index) => (
                        <div
                          key={index}
                          className='flex items-center gap-1 rounded-[20px] bg-background-glass-thin px-[12px] py-[6px] text-[14px]'
                        >
                          <span>{genre}</span>
                          <button
                            onClick={() => removeGenre(index)}
                            className='ml-1 text-[16px] leading-none text-foreground-secondary hover:text-foreground-primary'
                          >
                            ×
                          </button>
                        </div>
                      ))}
                    </div>
                  )}
                  {userInputtedGenres.length >= MAX_GENRES && (
                    <div className='mt-[4px] text-[12px] text-[#FF5757]'>
                      Maximum {MAX_GENRES} genres allowed
                    </div>
                  )}
                </div>

                <div className='mb-[32px]'>
                  <div className='mb-[8px] flex items-center justify-between'>
                    <label className='text-[14px] leading-[20px] font-medium'>
                      Section Order
                    </label>
                  </div>
                  <div className='mb-[12px] text-[12px] text-foreground-secondary'>
                    Drag to reorder how sections appear on your profile
                  </div>
                  <DndContext
                    sensors={sensors}
                    collisionDetection={closestCenter}
                    onDragEnd={handleSectionDragEnd}
                    modifiers={[restrictToVerticalAxis]}
                  >
                    <SortableContext
                      items={visibleSectionOrder}
                      strategy={verticalListSortingStrategy}
                    >
                      {visibleSectionOrder.map((sectionKey) => (
                        <SortableSectionItem
                          key={sectionKey}
                          id={sectionKey}
                          icon={
                            sectionTitles[
                              sectionKey as keyof typeof sectionTitles
                            ]?.icon
                          }
                          title={
                            sectionTitles[
                              sectionKey as keyof typeof sectionTitles
                            ]?.title || sectionKey
                          }
                        />
                      ))}
                    </SortableContext>
                  </DndContext>
                </div>

                <div className='mt-[24px] mb-[8px] text-[14px] leading-[20px] font-medium'>
                  Social networks
                </div>

                <InputField
                  value={spotifyLink}
                  onChange={(value) => {
                    setSpotifyLink(value);
                    if (!validateSpotifyUrl(value)) {
                      setSpotifyLinkError('Please enter a valid Spotify URL');
                    } else {
                      setSpotifyLinkError('');
                    }
                  }}
                  maxLength={200}
                  required={false}
                  error={spotifyLinkError}
                  leftAddon={
                    <SpotifyIcon className='mr-[8px] h-[24px] w-[16px]' />
                  }
                  className='mb-[8px]'
                  placeholder='https://open.spotify.com/your-profile'
                />
                <InputField
                  value={soundcloudLink}
                  onChange={(value) => {
                    setSoundcloudLink(value);
                    if (!validateSoundcloudUrl(value)) {
                      setSoundcloudLinkError(
                        'Please enter a valid SoundCloud URL'
                      );
                    } else {
                      setSoundcloudLinkError('');
                    }
                  }}
                  error={soundcloudLinkError}
                  leftAddon={
                    <SoundcloudIcon className='mr-[8px] h-[24px] w-[16px]' />
                  }
                  className='mb-[8px]'
                  placeholder='https://soundcloud.com/your-profile'
                />
                <InputField
                  value={xLink}
                  onChange={(value) => {
                    setXLink(value);
                    if (!validateXUrl(value)) {
                      setXLinkError('Please enter a valid X/Twitter URL');
                    } else {
                      setXLinkError('');
                    }
                  }}
                  error={xLinkError}
                  leftAddon={
                    <TwitterXIcon className='mr-[8px] h-[24px] w-[16px]' />
                  }
                  className='mb-[8px]'
                  placeholder='https://x.com/your-profile'
                />
                <InputField
                  value={instagramLink}
                  onChange={(value) => {
                    setInstagramLink(value);
                    if (!validateInstagramUrl(value)) {
                      setInstagramLinkError(
                        'Please enter a valid Instagram URL'
                      );
                    } else {
                      setInstagramLinkError('');
                    }
                  }}
                  error={instagramLinkError}
                  leftAddon={
                    <InstagramIcon className='mr-[8px] h-[24px] w-[16px]' />
                  }
                  className='mb-[8px]'
                  placeholder='https://www.instagram.com/your-profile'
                />
                <InputField
                  value={youtubeLink}
                  onChange={(value) => {
                    setYoutubeLink(value);
                    if (!validateYoutubeUrl(value)) {
                      setYoutubeLinkError('Please enter a valid YouTube URL');
                    } else {
                      setYoutubeLinkError('');
                    }
                  }}
                  error={youtubeLinkError}
                  leftAddon={
                    <YoutubeIcon className='mr-[8px] h-[24px] w-[16px]' />
                  }
                  placeholder='https://www.youtube.com/your-profile'
                />
              </div>
            </div>
          </div>
          <div className='mt-auto p-6 pb-0'>
            {moderationError && (
              <div className='mb-4 rounded-[12px] border border-[#FF5757]/20 bg-[#FF5757]/10 p-3'>
                <p className='mx-auto max-w-[70%] text-center text-[14px] font-medium text-[#FF5757]'>
                  {moderationError}
                </p>
              </div>
            )}
            <div className='flex justify-between gap-4'>
              <Button
                size={ButtonSize.Medium}
                variant={ButtonVariant.Secondary}
                onClick={() => handleClose('cancel')}
                disabled={isSubmitting}
                className='flex-1 rounded-[100px] py-[12px]'
              >
                Cancel
              </Button>
              <Button
                size={ButtonSize.Medium}
                variant={ButtonVariant.Primary}
                onClick={handleSubmit}
                disabled={
                  isSubmitting ||
                  !displayName.trim() ||
                  !handle.trim() ||
                  hasSocialLinkErrors()
                }
                className='flex-1 rounded-[100px] py-[12px]'
              >
                {isSubmitting ? 'Saving...' : 'Save'}
              </Button>
            </div>
          </div>
        </div>
      </Modal>
    );
  }
);

export default ProfileEditModal;
