'use client';

/* eslint jsx-a11y/label-has-associated-control: warn */
import { observer } from 'mobx-react-lite';
import { useEffect, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import Button, { ButtonSize, ButtonVariant } from '@/components/button/Button';
import ImageUploader from '@/components/image/ImageUploader';
import Modal from '@/components/modal/Modal';
import { TextInput } from '@/components/textarea/TextInput';
import TextareaV2 from '@/components/textarea/TextareaV2';
import { toast } from '@/components/toast/Toast';
import { PlanFeature } from '@/state/sessionStore';
import { USERNAME_VALIDATION_REGEX } from '@/utils/constants';
import { isFeatureEnabledForPlan } from '@/utils/session';

import SpinnerSVG from '../svg/SpinnerSVG';

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

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

const INVALID_HANDLE_ERROR_MSG =
  'This user handle is invalid. Must be at least 3 characters, and only letters, numbers and underscores are allowed';

const NAMES_MAX_LENGTH = 40;

export const ArtistProfileForm = observer(
  ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void }) => {
    const { session, library } = useStores();

    const [displayName, setDisplayName] = useState<string | null>(
      session.user?.display_name
    );
    const [handle, setHandle] = useState<string | null>(session.user?.handle);
    const [profileDescription, setProfileDescription] = useState<string | null>(
      session.user?.profile_description
    );
    const [imageDataURL, setImageDataURL] = useState<string | null>(null);
    const [imageChanged, setImageChanged] = useState(false);

    // Image upload in playlist metadata modal
    const [initialImageURL, setInitialImageURL] = useState<string | null>(
      session.user?.avatar_image_url
    );
    const [isGenerating, setIsGenerating] = useState(false);
    const [editedImagePrompt, setEditedImagePrompt] = useState<string>('');

    const [errors, setErrors] = useState<{
      [type: string]: string | undefined;
    }>({});
    const [submitLoading, setSubmitLoading] = useState<boolean>(false);

    const handleSubmit = async () => {
      setSubmitLoading(true);
      const response = await library.apiClient.POST('/api/profiles/', {
        body: {
          handle: handle || '',
          profile_description: profileDescription || '',
          display_name: displayName || '',
          avatar_image_url: imageDataURL,
        },
      });

      setSubmitLoading(false);
      if (response.error) {
        const newErrors = (response as any).error;
        setErrors({
          ...errors,
          ...newErrors,
        });
      } else {
        setErrors({});
        session.user.display_name = displayName || '';
        session.user.handle = handle || '';
        session.user.profile_description = profileDescription || '';
        session.user.avatar_image_url = imageDataURL;
        toast({
          title: 'Profile updated.',
          duration: 4000,
          isClosable: true,
          status: 'info',
        });
      }
    };

    useEffect(() => {
      setHandle(session.user?.handle);
      setProfileDescription(session.user?.profile_description);
      setDisplayName(session.user?.display_name);
    }, [session.user]);

    return (
      <>
        {isOpen && (
          <Modal
            onClose={onClose}
            title='Edit Profile'
            width={500}
            wrapperClasses='overflow-y-auto'
            contentWrapperClasses='rounded-2xl'
            titleWrapperClasses='pb-0'
          >
            <div className='min-w-[300px] md:min-w-[380px]'>
              <div className='flex w-full flex-col'>
                {/* Profile Avatar */}
                <div className='mt-8 w-full'>
                  <label className='mb-2 block text-sm font-medium'>
                    Profile Avatar
                  </label>
                  <ImageUploader
                    initialImageURL={initialImageURL || undefined}
                    onImageChanged={(imageData: string | null) => {
                      setImageDataURL(imageData);
                      setImageChanged(true);
                    }}
                    className='h-auto'
                  />

                  {isFeatureEnabledForPlan(
                    session,
                    PlanFeature.GenerateSongImage
                  ) && (
                    <>
                      <div className='mt-2 flex gap-2'>
                        <TextInput
                          type='text'
                          placeholder='Prompt Suno to create an image...'
                          value={editedImagePrompt}
                          maxLength={200}
                          onChange={(event) =>
                            setEditedImagePrompt(event.target.value)
                          }
                          className='flex-1 border border-foreground-primary/10 focus:border-foreground-primary'
                        />

                        <Button
                          className='rounded-2xl'
                          size={ButtonSize.Medium}
                          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 === ''}
                        >
                          Create
                        </Button>
                      </div>
                      {isGenerating && (
                        <div className='mt-2 flex flex-row'>
                          <SpinnerSVG className='mr-2' />
                          <span className='text-sm'>Creating image...</span>
                        </div>
                      )}
                    </>
                  )}
                  <p
                    className={`mt-1 text-sm ${errors.avatar_image_url ? 'text-red-300' : 'text-foreground-secondary'}`}
                  >
                    {errors.avatar_image_url ||
                      'The image that will be shown on your profile (max 10 MB)'}
                  </p>
                </div>

                {/* Display Name */}
                <div className='my-8'>
                  <label className='mb-2 block text-sm font-medium'>
                    Display Name
                  </label>
                  <TextInput
                    type='text'
                    className={`border border-foreground-primary/10 focus:border-foreground-primary ${
                      !validateDisplayName(displayName || '') ||
                      errors.display_name
                        ? 'border-red-300 focus:border-red-300'
                        : ''
                    }`}
                    maxLength={NAMES_MAX_LENGTH}
                    value={displayName || ''}
                    placeholder='Display Name'
                    onChange={(e) => {
                      setDisplayName(e.target.value);
                      setErrors({
                        ...errors,
                        display_name: undefined,
                      });
                    }}
                    data-testid='display-name-input'
                  />
                  <p className='mt-1 text-sm text-foreground-secondary'>
                    {errors.display_name ||
                      'This is shown on your songs and playlists.'}
                  </p>
                </div>

                {/* Handle */}
                <div className='mb-8'>
                  <label className='mb-2 block text-sm font-medium'>
                    Handle *
                  </label>
                  <div className='flex'>
                    <div className='flex items-center rounded-l-2xl border border-r-0 border-foreground-primary/10 bg-background-primary px-3'>
                      <span className='text-foreground-primary'>@</span>
                    </div>
                    <TextInput
                      type='text'
                      className={`flex-1 rounded-l-none border border-l-0 border-foreground-primary/10 focus:border-foreground-primary ${
                        !validateHandle(handle || '') || errors.handle
                          ? 'border-accent-error focus:border-accent-error'
                          : ''
                      }`}
                      maxLength={NAMES_MAX_LENGTH}
                      value={handle || ''}
                      placeholder='Handle'
                      onChange={(e) => {
                        setHandle(e.target.value);
                        setErrors({
                          ...errors,
                          handle: undefined,
                        });
                      }}
                      data-testid='handle-input'
                    />
                  </div>
                  <p
                    className={`mt-1 text-sm ${
                      !validateHandle(handle || '') || errors.handle
                        ? 'text-accent-error-on-primary'
                        : 'text-foreground-secondary'
                    }`}
                  >
                    {!validateHandle(handle || '')
                      ? INVALID_HANDLE_ERROR_MSG
                      : errors.handle ||
                        'This is used in your profile URL, and can be changed later.'}
                  </p>
                </div>

                {/* Profile Description */}
                <div className='mb-8'>
                  <label className='mb-2 block text-sm font-medium'>
                    Profile Description
                  </label>
                  <TextareaV2
                    className={`border ${errors.profile_description ? 'border-red-300' : 'border-foreground-primary/10'} w-full rounded-2xl bg-background-primary`}
                    value={profileDescription || ''}
                    placeholder='Profile description'
                    onChange={(e) => {
                      setProfileDescription(e.target.value);
                      setErrors({
                        ...errors,
                        profile_description: undefined,
                      });
                    }}
                    maxLength={160}
                    resize={true}
                    minRows={4}
                    data-testid='profile-description-input'
                  />
                  <p className='mt-1 text-sm text-foreground-secondary'>
                    {errors.profile_description ||
                      'Describe your musical style in a few words.'}
                  </p>
                </div>
              </div>

              {/* Footer */}
              <div className='mt-8 flex items-center justify-between'>
                <Button
                  variant={ButtonVariant.Primary}
                  size={ButtonSize.Medium}
                  onClick={handleSubmit}
                  disabled={
                    (displayName === session.user?.display_name &&
                      handle === session.user?.handle &&
                      profileDescription ===
                        session.user?.profile_description &&
                      !imageChanged) ||
                    !validateHandle(handle || '') ||
                    !validateDisplayName(displayName || '')
                  }
                  className='max-w-[200px]'
                >
                  {submitLoading ? 'Saving...' : 'Save'}
                </Button>

                {session.user?.display_name && (
                  <a
                    href={`/@${session.user?.handle}`}
                    className='text-foreground-primary transition-colors hover:text-foreground-secondary'
                  >
                    View My Profile
                  </a>
                )}
              </div>
            </div>
          </Modal>
        )}
      </>
    );
  }
);
