'use client';

import { useAuth } from '@clerk/nextjs';
import { useDynamicConfig, useGateValue } from '@statsig/react-bindings';
import clsx from 'clsx';
import React from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import {
  FadeInText,
  InviteCodeInput,
} from '@/components/studioWaitlist/components/TextEffects';
import {
  INVITE_CODE_LENGTH,
  SURVEY_PAD_X,
} from '@/components/studioWaitlist/constants';
import SpinnerSVG from '@/components/svg/SpinnerSVG';
import { ChevronRightIcon } from '@/icons';
import logWebUserEvent from '@/logging/logWebUserEvent';

import {
  ButtonRow,
  CheckboxGroup,
  SurveyContent,
  SurveyGrid,
  SurveyTitle,
} from './components/';
import EdgeToEdgeText from './components/EdgeToEdgeText';
import { useInviteCode } from './hooks/useInviteCode';
import type { ISlide, StudioWaitlistState } from './types';
import { SlideFlowStatus } from './types';

// ====================================
// React Components for Slide Content
// ====================================

// IntroSlideView component
function IntroSlideView({ ctx: _ctx }: { ctx: StudioWaitlistState }) {
  const welcomeMessage = 'Join Waitlist';

  return (
    <div
      className={clsx('flex w-full items-center justify-center', SURVEY_PAD_X)}
    >
      <div className='w-full max-w-[590px]'>
        <EdgeToEdgeText
          text={welcomeMessage}
          className='font-[500] text-white'
        />
      </div>
    </div>
  );
}

// SurveyQuestionView component with hooks for proper state management
function SurveyQuestionView({
  ctx,
  question,
}: {
  ctx: StudioWaitlistState;
  question: any;
}) {
  // Read current value
  const stored = ctx.getField?.('survey_' + question.id) ?? [];
  const rawValue: string[] = Array.isArray(stored) ? stored : [stored];

  // Normalize schema (support new + legacy)
  const title: string = question.question ?? question.prompt ?? '';
  const qTypeRaw = (question.question_type ?? question.type ?? '')
    .toString()
    .toUpperCase();

  const isSingle =
    qTypeRaw === 'SINGLE_CHOICE' ||
    qTypeRaw === 'RADIO' ||
    qTypeRaw === 'SINGLE';
  const isMulti =
    qTypeRaw === 'MULTIPLE_CHOICE' ||
    qTypeRaw === 'MULTI' ||
    qTypeRaw === 'CHECKBOX';
  const isText = qTypeRaw === 'TEXT' || qTypeRaw === 'INPUT';
  const isArea = qTypeRaw === 'PARAGRAPH' || qTypeRaw === 'TEXTAREA';

  const options = React.useMemo(() => {
    if (!Array.isArray(question.options))
      return [] as { id: string; label: string }[];
    const first = question.options[0];
    if (typeof first === 'string') {
      return (question.options as string[]).map((s) => ({ id: s, label: s }));
    }
    return (question.options as any[]).map((opt) => ({
      id: String(opt?.id ?? opt?.value ?? opt?.text ?? opt?.label ?? ''),
      label: String(opt?.text ?? opt?.label ?? opt?.value ?? opt?.id ?? ''),
    }));
  }, [question.options]);

  const setArrayField = React.useCallback(
    (next: string[]) => ctx.setField?.('survey_' + question.id, next),
    [ctx, question.id]
  );

  const setScalarField = React.useCallback(
    (next: string) => ctx.setField?.('survey_' + question.id, [next]),
    [ctx, question.id]
  );

  // TEXT input
  if (isText) {
    const val = rawValue[0] ?? '';
    return (
      <SurveyGrid>
        <SurveyTitle>{title}</SurveyTitle>
        <SurveyContent>
          <div className='mt-2 md:mt-0'>
            <input
              type='text'
              value={val}
              onChange={(e) => setScalarField(e.target.value)}
              className='w-full rounded-lg border border-white/20 bg-white/10 px-4 py-3 text-lg text-white placeholder-white/50 focus:border-white/40 focus:outline-none'
              placeholder='Enter your answer...'
            />
          </div>
        </SurveyContent>
      </SurveyGrid>
    );
  }

  // TEXTAREA
  if (isArea) {
    const val = rawValue[0] ?? '';
    return (
      <SurveyGrid>
        <SurveyTitle>{title}</SurveyTitle>
        <SurveyContent>
          <div className='mt-2 w-full md:mt-0'>
            <textarea
              value={val}
              onChange={(e) => setScalarField(e.target.value)}
              className={clsx(
                'w-full resize-none rounded-lg',
                'min-h-[120px] md:h-[200px] md:min-h-0',
                'border border-white/20 bg-white/10',
                'px-4 py-3 text-lg text-white',
                'placeholder-white/50',
                'focus:border-white/40 focus:outline-none'
              )}
              placeholder='Enter your answer...'
            />
          </div>
        </SurveyContent>
      </SurveyGrid>
    );
  }

  // CHOICE (single/multi)
  if ((isSingle || isMulti) && options.length > 0) {
    return (
      <SurveyGrid>
        <SurveyTitle>{title}</SurveyTitle>
        <SurveyContent>
          <div className='mt-2 md:mt-0'>
            <CheckboxGroup
              options={options}
              value={rawValue}
              onChange={setArrayField}
              multiple={!isSingle}
              className='mt-2 md:mt-0'
            />
          </div>
        </SurveyContent>
      </SurveyGrid>
    );
  }

  // Fallback
  return (
    <SurveyGrid>
      <SurveyTitle>{title || 'Question'}</SurveyTitle>
      <SurveyContent>
        <div className='mt-2 text-sm text-white/70 md:mt-0'>
          This question is not configured properly.
        </div>
      </SurveyContent>
    </SurveyGrid>
  );
}

// Common Footer Button Components
interface SkipToWaitlistButtonProps {
  onClick?: () => void;
  variant?: ButtonVariant;
  className?: string;
  children?: React.ReactNode;
}

const SkipToWaitlistButton: React.FC<SkipToWaitlistButtonProps> = ({
  onClick,
  className = '',
  children = 'Skip to waitlist',
}) => (
  <button
    aria-label='Skip to waitlist'
    className={clsx(
      'cursor-pointer bg-transparent font-medium text-white/70 transition-colors duration-200 hover:text-white',
      className
    )}
    onClick={onClick}
  >
    {children}
  </button>
);

interface NextButtonProps {
  onClick?: () => void;
  children?: React.ReactNode;
  className?: string;
  disabled?: boolean;
}

const NextButton: React.FC<NextButtonProps> = ({
  onClick,
  children = 'Next',
  className = 'h-14 w-[109px] justify-center bg-white/90 disabled:opacity-40 disabled:brightness-100',
  disabled = false,
}) => (
  <Button
    variant={ButtonVariant.Primary}
    size={ButtonSize.Medium}
    shape={ButtonShape.Pill}
    className={className}
    onClick={onClick || (() => {})}
    disabled={disabled}
    href={undefined as never}
  >
    {children}
  </Button>
);

interface JoinWaitlistButtonProps {
  onClick?: () => void;
  disabled?: boolean;
  loading?: boolean;
  className?: string;
  children?: React.ReactNode;
}

export const JoinWaitlistButton: React.FC<JoinWaitlistButtonProps> = ({
  onClick,
  disabled = false,
  loading = false,
  className = 'h-14 bg-white/90 px-9 disabled:opacity-40 disabled:brightness-100',
  children = 'Join Waitlist',
}) => (
  <Button
    variant={ButtonVariant.Primary}
    size={ButtonSize.Medium}
    shape={ButtonShape.Pill}
    className={className}
    aria-label={typeof children === 'string' ? children : 'Join Waitlist'}
    disabled={disabled || loading}
    onClick={onClick || (() => {})}
    href={undefined as never}
  >
    {children}
  </Button>
);

interface NavigationButtonsProps {
  onSkip?: () => void;
  onNext?: () => void;
  nextButtonContent?: React.ReactNode;
  nextButtonClassName?: string;
  skipButtonClassName?: string;
  skipButtonContent?: React.ReactNode;
}

const NavigationButtons: React.FC<NavigationButtonsProps> = ({
  onSkip,
  onNext,
  nextButtonContent = 'Next',
  nextButtonClassName,
  skipButtonClassName,
  skipButtonContent = 'Skip to waitlist',
}) => (
  <ButtonRow>
    <SkipToWaitlistButton onClick={onSkip} className={skipButtonClassName}>
      {skipButtonContent}
    </SkipToWaitlistButton>
    <NextButton onClick={onNext} className={nextButtonClassName}>
      {nextButtonContent}
    </NextButton>
  </ButtonRow>
);

// IntroSlide - Landing screen without questions
export const IntroSlide: ISlide<StudioWaitlistState> = {
  id: 'intro',
  shouldShowSegments: (_ctx) => false,
  renderContent: (ctx) => <IntroSlideView ctx={ctx} />,
  renderButtons: (ctx) => (
    <ButtonRow>
      <NextButton onClick={() => ctx?.goNext?.()}>
        <ChevronRightIcon className='scale-125 text-black' />
      </NextButton>
    </ButtonRow>
  ),
};

// Survey Question Slide Factory
export function createSurveyQuestionSlide(
  question: any
): ISlide<StudioWaitlistState> {
  return {
    id: `survey-${question.id}`,
    shouldShowSegments: (_ctx) => true,
    renderContent: (ctx) => (
      <SurveyQuestionView ctx={ctx} question={question} />
    ),
    renderButtons: (ctx) => {
      const hasInviteCode = !!ctx?.getCachedInviteCode?.();
      const skipText = hasInviteCode ? 'Skip' : 'Skip to waitlist';

      return (
        <NavigationButtons
          onSkip={() => ctx?.skipToLastSlide?.()}
          onNext={() => ctx?.goNext?.()}
          skipButtonContent={skipText}
        />
      );
    },
  };
}

// InviteCodeView component that uses the useInviteCode hook (original UX)
function InviteCodeView({ ctx }: { ctx: StudioWaitlistState }) {
  const { code: inviteCode, validateCode } = useInviteCode();
  const [val, setVal] = React.useState('');
  const [errorMessage, setErrorMessage] = React.useState<string | null>(null);
  const [loading, setLoading] = React.useState(false);

  // Pull out stable functions from ctx
  const { registerFocusTarget, setField } = ctx;
  const disabled = React.useMemo(() => {
    return val.length !== INVITE_CODE_LENGTH;
  }, [val]);

  // Set invite code value when available from URL
  React.useEffect(() => {
    if (inviteCode) {
      setVal(inviteCode);
    }
  }, [inviteCode]);

  // Expose the hidden input to the outer panel for click-to-focus - only once
  const inputRef = React.useRef<HTMLInputElement>(null);
  React.useEffect(() => {
    registerFocusTarget?.(inputRef);
    return () => registerFocusTarget?.(null);
  }, [registerFocusTarget]);

  // Store state in context so buttons can access it - only when values change
  React.useEffect(() => {
    setField?.('inviteCode_val', val);
    setField?.('inviteCode_disabled', disabled);
    setField?.('inviteCode_loading', loading);
    setField?.('inviteCode_errorMessage', errorMessage);
  }, [val, disabled, loading, errorMessage, setField]);

  const handleSubmit = React.useCallback(async () => {
    if (disabled || loading) return;
    setLoading(true);
    setErrorMessage(null);

    const result = await validateCode(val);
    if (result.success) {
      ctx.setCachedInviteCode?.(val);
      ctx?.goNext?.();
    } else if (result.error) {
      setErrorMessage(result.error);
    }
    setLoading(false);
  }, [disabled, loading, validateCode, val, ctx]);

  // Store the submit handler in context - use stable setField reference
  React.useEffect(() => {
    setField?.('inviteCode_handleSubmit', handleSubmit);
  }, [setField, handleSubmit]);

  return (
    <div
      className={clsx('flex w-full items-center justify-center', SURVEY_PAD_X)}
    >
      <div className='w-full max-w-[490px]'>
        <InviteCodeInput
          minLength={INVITE_CODE_LENGTH}
          value={val}
          onChange={setVal}
          className='text-white'
        />
      </div>
    </div>
  );
}

// InviteCodeSlide component function that handles state sharing
export function createInviteCodeSlide(): ISlide<StudioWaitlistState> {
  return {
    id: 'invite-code',
    shouldShowSegments: (_ctx) => false,
    renderContent: (ctx) => <InviteCodeView ctx={ctx} />,
    renderButtons: (ctx) => {
      const disabled = ctx.getField?.('inviteCode_disabled') ?? true;
      const loading = ctx.getField?.('inviteCode_loading') ?? false;
      const errorMessage = ctx.getField?.('inviteCode_errorMessage');
      const handleSubmit = ctx.getField?.('inviteCode_handleSubmit');

      return (
        <ButtonRow>
          {errorMessage && (
            <div className='flex items-center'>
              <svg
                width='24'
                height='24'
                viewBox='0 0 24 24'
                fill='none'
                xmlns='http://www.w3.org/2000/svg'
              >
                <path
                  d='M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zM13 17h-2v-2h2v2zm0-4h-2V7h2v6z'
                  fill='#F7F4EF'
                />
              </svg>
              <span className='ml-2 text-sm font-medium text-[rgba(250,247,245,0.75)]'>
                {errorMessage}
              </span>
            </div>
          )}
          <NextButton onClick={handleSubmit} disabled={disabled || loading}>
            {loading ? (
              <SpinnerSVG className='h-5 w-5 animate-spin text-black' />
            ) : (
              <ChevronRightIcon className='scale-125 text-black' />
            )}
          </NextButton>
        </ButtonRow>
      );
    },
  };
}

// DoneSlideView component that calls expandMask on mount
function DoneSlideView({ ctx }: { ctx: StudioWaitlistState }) {
  const { isLoaded: _isLoaded } = useAuth();
  const showTotal = useGateValue('studio-waitlist-total');
  const studioConfig = useDynamicConfig('studio-waitlist-config');
  const { session } = useStores();

  React.useEffect(() => {
    ctx.expandMask();
    /* advance global progress  */
    ctx.updateStatus?.(SlideFlowStatus.TRANSITION_DONE);
  }, [ctx]);

  // Get user's first name from display name (split on space, take first part)
  const firstName = session.user?.display_name?.split(' ')[0] || null;

  // Show welcome message based on studio access
  const showWelcome = ctx.hasStudioAccess;

  // Get dynamic config values
  const studioRedirectUrl = studioConfig.get('studio_redirect_url', '/studio');
  const studioButtonText = studioConfig.get(
    'studio_redirect_button_text',
    'Enter Studio'
  );

  // Determine the message to display
  const welcomeMessage = showWelcome
    ? firstName
      ? `Welcome, ${firstName}!`
      : 'Welcome!'
    : "You're on the list";

  return (
    <div className='flex flex-1 items-center justify-start md:justify-center'>
      <div className='grid w-full max-w-[790px] grid-cols-1 gap-y-10 md:gap-y-8'>
        <div className='text-left md:text-center'>
          <EdgeToEdgeText fullText={welcomeMessage} className='text-white'>
            <FadeInText delay={500}>{welcomeMessage}</FadeInText>
          </EdgeToEdgeText>
        </div>
        {showWelcome && (
          <div className='flex justify-center'>
            <FadeInText delay={500}>
              <Button
                variant={ButtonVariant.Primary}
                size={ButtonSize.Medium}
                shape={ButtonShape.Pill}
                className='flex h-14 items-center justify-center bg-white/90 px-9 transition-colors'
                href={studioRedirectUrl}
                onClick={() => {
                  logWebUserEvent({
                    actionName: 'NavigatedToStudio',
                    context: {
                      trigger: 'studio_waitlist_welcome',
                    },
                  });
                }}
              >
                {studioButtonText}
              </Button>
            </FadeInText>
          </div>
        )}
        {!showWelcome && (
          <div className='grid grid-cols-1 gap-y-6 md:grid-cols-2 md:gap-y-0'>
            <p className='text-[18px] text-white'>
              <FadeInText delay={700}>
                You&apos;ll be one of the first in.
              </FadeInText>
            </p>
            {showTotal && (
              <p className='text-[18px] text-white md:text-right'>
                <FadeInText delay={700}>
                  {ctx.waitlistResponseLoaded
                    ? ctx.waitlistSize !== undefined
                      ? `${ctx.waitlistSize.toLocaleString()} ${ctx.waitlistSize === 1 ? 'person' : 'people'} on the waitlist.`
                      : ctx.waitlistRank
                        ? `You're #${ctx.waitlistRank.toLocaleString()} on the list.`
                        : "You're on the list."
                    : "You're on the list."}
                </FadeInText>
              </p>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

// DoneSlide - Simple thank-you screen only
export function createDoneSlide(): ISlide<StudioWaitlistState> {
  return {
    id: 'done',
    shouldShowSegments: (_ctx) => false,
    renderContent: (ctx) => <DoneSlideView ctx={ctx} />,
    renderButtons: () => <></>,
  };
}
