'use client';

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

import { useStores } from '@/app/(root)/AppProviders';
import ImageUploader from '@/components/image/ImageUploader';
import logWebUserEvent from '@/logging/logWebUserEvent';
import { EditPersonaParams } from '@/state/personaStore';
import { PlanFeature } from '@/state/sessionStore';
import { MAX_DESCRIPTION_LENGTH, SUPER_MODAL_Z_INDEX } from '@/utils/constants';
import { isFeatureEnabledForPlan } from '@/utils/session';

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

interface EditPersonaModalProps {
  isOpen: boolean;
  onClose: () => void;
  persona: any;
  onUpdate: (updatedPersona: any) => void;
}

const EditPersonaModal: React.FC<EditPersonaModalProps> = observer(
  ({ isOpen, onClose, persona, onUpdate }) => {
    const { persona: personaState, session, library } = useStores();
    const [name, setName] = useState<string>(persona.name);
    const [description, setDescription] = useState<string>(persona.description);
    const [imageDataURL, setImageDataURL] = useState<string | null>(
      persona.image_s3_id
    );
    const [initialImageDataURL, setInitialImageDataURL] = useState<
      string | null
    >(persona.image_s3_id);
    const [isLoading, setIsLoading] = useState(false);
    const [errorMessage, setErrorMessage] = useState<string | null>(null);
    const [isGenerating, setIsGenerating] = useState(false);
    const [editedImagePrompt, setEditedImagePrompt] = useState<string>('');

    const modalRef = useRef<HTMLDivElement>(null);
    const isInitialMount = useRef(true);

    const handleDescriptionChange = (
      e: React.ChangeEvent<HTMLTextAreaElement>
    ) => {
      if (e.target.value.length <= MAX_DESCRIPTION_LENGTH) {
        setDescription(e.target.value);
      }
    };

    const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      setName(e.target.value);
    };

    const handleSave = async () => {
      setIsLoading(true);
      setErrorMessage(null);

      const updatedPersona = {
        ...persona,
        name,
        description,
        image_s3_id: imageDataURL,
      };

      const params: EditPersonaParams = {
        persona_id: persona.id,
        name,
        description,
        image_s3_id: imageDataURL,
      };

      logWebUserEvent({
        actionName: 'PersonaEditClicked',
        context: {
          personaId: updatedPersona?.id,
        },
      });

      try {
        const result = await personaState.editPersona(params);
        if (result) {
          onUpdate(updatedPersona);
          onClose();
        }
      } catch (error) {
        console.error('Error editing persona:', error);
        setErrorMessage('An error occurred while editing the persona.');
        onUpdate(persona);
      } finally {
        setIsLoading(false);
      }
    };

    const handleOutsideClick = useCallback(
      (event: MouseEvent) => {
        if (
          modalRef.current &&
          !modalRef.current.contains(event.target as Node)
        ) {
          onClose();
        }
      },
      [onClose]
    );
    const resetModalState = useCallback(() => {
      setName(persona.name);
      setDescription(persona.description);
      setImageDataURL(persona.image_s3_id);
      setInitialImageDataURL(persona.image_s3_id);
      setErrorMessage(null);
      setEditedImagePrompt('');
    }, [persona]);

    const handleClose = useCallback(() => {
      resetModalState();
      onClose();
      logWebUserEvent({
        actionName: 'EditPersonaModalCloseClicked',
      });
    }, [onClose, resetModalState]);

    useEffect(() => {
      if (isOpen && isInitialMount.current) {
        resetModalState();
        isInitialMount.current = false;
      }

      if (!isOpen) {
        isInitialMount.current = true;
      }

      if (isOpen) {
        document.addEventListener('mousedown', handleOutsideClick);
      } else {
        document.removeEventListener('mousedown', handleOutsideClick);
      }

      return () => {
        document.removeEventListener('mousedown', handleOutsideClick);
      };
    }, [isOpen, handleOutsideClick]);

    useEffect(() => {
      if (!isOpen) {
        setName(persona.name);
        setDescription(persona.description);
        setImageDataURL(persona.image_s3_id);
        setInitialImageDataURL(persona.image_s3_id);
      }
    }, [persona, isOpen]);

    if (!isOpen) return null;

    return (
      <div
        className='fixed inset-0 flex items-center justify-center bg-black/50'
        style={{ zIndex: SUPER_MODAL_Z_INDEX }}
      >
        <div
          ref={modalRef}
          className='w-[500px] rounded-lg bg-background-tertiary p-6 text-foreground-primary'
        >
          <div className='flex items-center justify-between pb-4'>
            <h2 className='p-2 font-serif text-3xl'>Edit Persona</h2>
            <CloseButton onClick={handleClose} />
          </div>
          {errorMessage && (
            <div className='mb-4 text-sm text-accent-pink'>{errorMessage}</div>
          )}
          <div className='mb-4'>
            <label className='mb-1 block p-1'>Name</label>
            <input
              type='text'
              className='focus:border-0.5 placeholder-opacity-70 w-full rounded-lg border border-border-secondary bg-background-tertiary p-2 text-foreground-primary placeholder-foreground-secondary focus:border focus:border-accent-brand focus:shadow-[0_0_0_0.5px_accent-brand] focus:outline-none'
              value={name}
              placeholder='Name this persona...'
              onChange={handleNameChange}
            />
          </div>
          <div className='mb-4'>
            <label className='mb-1 block p-1'>Avatar</label>
            <ImageUploader
              initialImageURL={initialImageDataURL || undefined}
              onImageChanged={(imageData: string | null) => {
                setImageDataURL(imageData);
              }}
            />
            {isFeatureEnabledForPlan(session, PlanFeature.EditMode) && (
              <>
                <div className='mt-2 flex gap-2 pt-1'>
                  <input
                    type='text'
                    className='focus:border-0.5 placeholder-opacity-70 w-full rounded-lg border border-border-secondary bg-background-tertiary p-2 text-sm text-foreground-primary placeholder-foreground-secondary focus:border focus:border-accent-brand focus:shadow-[0_0_0_0.5px_accent-brand] focus:outline-none'
                    value={editedImagePrompt}
                    maxLength={200}
                    placeholder='Prompt Suno to create an image...'
                    onChange={(event) =>
                      setEditedImagePrompt(event.target.value)
                    }
                  />
                  <Button
                    variant={ButtonVariant.Primary}
                    onClick={async () => {
                      setIsGenerating(true);
                      const { data } = await library.apiClient.POST(
                        '/api/gen/prompt_image/',
                        {
                          body: {
                            prompt: editedImagePrompt,
                          },
                        }
                      );
                      setIsGenerating(false);
                      if (data) {
                        setInitialImageDataURL((data as any).image_url);
                      }
                    }}
                    disabled={isGenerating || editedImagePrompt === ''}
                    icon={isGenerating && <SpinnerSVG />}
                  >
                    Create
                  </Button>
                </div>
              </>
            )}
          </div>
          <div className='mb-4'>
            <label className='mb-2 block'>Description</label>
            <textarea
              className='focus:border-0.5 placeholder-opacity-70 w-full rounded-lg border border-border-secondary bg-background-tertiary p-2 text-foreground-primary placeholder-foreground-secondary focus:border focus:border-accent-brand focus:shadow-[0_0_0_0.5px_accent-brand] focus:outline-none'
              rows={4}
              value={description}
              placeholder="Describe this Persona's sound or bio"
              onChange={handleDescriptionChange}
              maxLength={MAX_DESCRIPTION_LENGTH}
            />
            <div className='text-right text-sm text-foreground-secondary'>
              {description.length}/{MAX_DESCRIPTION_LENGTH}
            </div>
          </div>
          <div className='flex justify-end gap-2'>
            <Button onClick={handleClose}>Close</Button>
            <Button
              variant={ButtonVariant.Primary}
              onClick={handleSave}
              icon={isLoading && <SpinnerSVG />}
            >
              Save
            </Button>
          </div>
        </div>
      </div>
    );
  }
);

export default EditPersonaModal;
