'use client';

import {
  Alert,
  AlertIcon,
  Box,
  Button,
  Divider,
  Flex,
  Heading,
  List,
  ListIcon,
  ListItem,
  Text,
} from '@chakra-ui/react';
import { useAuth } from '@clerk/nextjs';
import { useRouter, useSearchParams } from 'next/navigation';
import { useEffect, useState } from 'react';

import SpinnerSVG from '@/components/svg/SpinnerSVG';
import { SuccessIcon } from '@/icons';

export default function OAuthAuthorizePage() {
  const { isLoaded, isSignedIn, getToken } = useAuth();
  const router = useRouter();
  const searchParams = useSearchParams();
  const [isStoring, setIsStoring] = useState(false);
  const [clientName, setClientName] = useState('');
  const [scopes, setScopes] = useState<string[]>([]);
  const [status, setStatus] = useState('Preparing account linking...');
  const [error, setError] = useState('');
  const [isProcessing, setIsProcessing] = useState(false);
  const [showConsent, setShowConsent] = useState(false);

  // Parse and store OAuth parameters
  useEffect(() => {
    if (!isLoaded) return;

    // Check if we have stored parameters from a previous redirect
    const storedParams = localStorage.getItem('oauth_params');

    // If we have URL parameters, use those (initial OAuth request)
    if (searchParams && searchParams.get('client_id')) {
      setIsStoring(true);

      const params = {
        client_id: searchParams.get('client_id'),
        redirect_uri: searchParams.get('redirect_uri'),
        state: searchParams.get('state'),
        scope: searchParams.get('scope'),
      };

      // Check for required parameters
      if (!params.client_id || !params.redirect_uri || !params.state) {
        const missingParams = [];
        if (!params.client_id) missingParams.push('client_id');
        if (!params.redirect_uri) missingParams.push('redirect_uri');
        if (!params.state) missingParams.push('state');

        setError(
          `Missing required OAuth parameters: ${missingParams.join(', ')}`
        );
        setIsStoring(false);
        return;
      }

      // Store parameters in localStorage
      localStorage.setItem('oauth_params', JSON.stringify(params));

      // Parse scope to display to user
      if (params.scope) {
        const scopeArray = params.scope.split(' ');
        setScopes(scopeArray);
      }

      // Get client name based on client_id
      const clientId = params.client_id;
      fetchClientName(clientId);

      setIsStoring(false);

      // If user is signed in, show consent screen
      if (isSignedIn) {
        setShowConsent(true);
      } else {
        // Otherwise redirect to login with return URL preserving OAuth flow
        // We've already saved params in localStorage, so redirect to login
        const redirectPath = `/login?redirect_to=${encodeURIComponent('/link-account')}`;
        router.push(redirectPath);
      }
    }
    // If we returned from login and have stored parameters
    else if (storedParams && isSignedIn) {
      try {
        const params = JSON.parse(storedParams);

        if (params.scope) {
          setScopes(params.scope.split(' '));
        }

        // Get client name
        fetchClientName(params.client_id);

        // Show consent screen
        setShowConsent(true);
      } catch (error) {
        setError('Invalid OAuth parameters. Please try again.');
      }
    }
    // No parameters in URL or localStorage
    else if (!storedParams) {
      setError(
        'No OAuth parameters found. Please try again with a valid authorization URL.'
      );
    }
    // Have stored params but user is not signed in
    else if (storedParams && !isSignedIn) {
      // We'll rely on the redirect to login now
    }
  }, [isLoaded, isSignedIn, router, searchParams]);

  // Fetch client name from API
  const fetchClientName = async (clientId: string | null) => {
    if (!clientId) {
      setClientName('Unknown Application');
      return;
    }

    try {
      const token = await getToken();
      if (!token) {
        setClientName(`External Application (${clientId})`);
        return;
      }

      const apiBase = process.env.NEXT_PUBLIC_API_BASE;

      const response = await fetch(
        `${apiBase}/api/v2/external/oauth/client-info?client_id=${clientId}`,
        {
          headers: {
            Authorization: `Bearer ${token}`,
          },
        }
      );

      if (response.ok) {
        const data = await response.json();
        setClientName(data.name || 'External Application');
      } else {
        setClientName(`External Application (${clientId})`);
      }
    } catch (error) {
      setClientName(`External Application (${clientId})`);
    }
  };

  const handleAuthorize = async () => {
    setIsProcessing(true);
    setStatus('Generating authorization code...');

    try {
      // Get stored OAuth parameters
      const paramsStr = localStorage.getItem('oauth_params');

      if (!paramsStr) {
        setError('Missing OAuth parameters. Please try again.');
        setIsProcessing(false);
        return;
      }

      const params = JSON.parse(paramsStr);

      // Get Clerk auth token
      const token = await getToken();
      if (!token) {
        setError('Authentication failed. Please sign in again.');
        setIsProcessing(false);
        return;
      }

      // Call backend API
      const apiBase = process.env.NEXT_PUBLIC_API_BASE;

      const response = await fetch(
        `${apiBase}/api/v2/external/oauth/generate-code`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${token}`,
          },
          body: JSON.stringify(params),
        }
      );

      if (!response.ok) {
        const errorText = await response.text();

        try {
          const errorData = JSON.parse(errorText);
          setError(
            errorData.error || 'Failed to link account. Please try again.'
          );
        } catch (e) {
          setError(`Server error: ${response.status} - ${errorText}`);
        }

        setIsProcessing(false);
        return;
      }

      const data = await response.json();

      setStatus('Redirecting to complete account linking...');

      // Clean up
      localStorage.removeItem('oauth_params');

      // Redirect to partner application
      window.location.href = data.redirect_url;
    } catch (error) {
      setError('An unexpected error occurred. Please try again.');
      setIsProcessing(false);
    }
  };

  const handleCancel = () => {
    // Clean up stored params
    localStorage.removeItem('oauth_params');
    // Redirect to home
    router.push('/');
  };

  // Map scopes to human-readable descriptions
  const getScopeDescription = (scope: string) => {
    const scopeMap: Record<string, string> = {
      read_profile: 'Read your profile information',
      generate_music: 'Generate music with Suno on your behalf',
      read_music: 'Access your music library',
    };

    return scopeMap[scope] || scope;
  };

  // Render loading state
  if (!isLoaded || isStoring || isProcessing) {
    return (
      <Box
        maxW='container.sm'
        mx='auto'
        py={10}
        px={4}
        textAlign='center'
        color='white'
      >
        <Heading as='h1' size='xl' mb={6}>
          {showConsent ? 'Authorize Application' : 'Linking Your Suno Account'}
        </Heading>

        <Flex direction='column' align='center'>
          <SpinnerSVG className='mb-4 size-8' />
          <Text fontSize='lg'>{status}</Text>
        </Flex>
      </Box>
    );
  }

  // Render error state
  if (error) {
    return (
      <Box
        maxW='container.sm'
        mx='auto'
        py={10}
        px={4}
        textAlign='center'
        color='white'
      >
        <Heading as='h1' size='xl' mb={6}>
          Account Linking Error
        </Heading>
        <Alert status='error' borderRadius='md'>
          <AlertIcon />
          {error}
        </Alert>
      </Box>
    );
  }

  // Render consent screen
  if (showConsent) {
    return (
      <Box
        maxW='container.sm'
        mx='auto'
        py={10}
        px={6}
        textAlign='center'
        color='white'
      >
        <Heading as='h1' size='xl' mb={4}>
          Authorize Access
        </Heading>

        <Text fontSize='lg' mb={6}>
          <strong>{clientName}</strong> would like to access your Suno account
        </Text>

        <Box
          bg='gray.800'
          p={6}
          borderRadius='md'
          textAlign='left'
          mb={8}
          color='white'
        >
          <Text fontWeight='bold' mb={3}>
            This will allow {clientName} to:
          </Text>
          <List spacing={3}>
            {scopes.map((scope) => (
              <ListItem key={scope}>
                <ListIcon as={SuccessIcon} color='green.400' />
                {getScopeDescription(scope)}
              </ListItem>
            ))}
          </List>
        </Box>

        <Divider mb={6} />

        <Flex justify='space-between'>
          <Button colorScheme='gray' onClick={handleCancel} size='lg'>
            Cancel
          </Button>
          <Button colorScheme='blue' onClick={handleAuthorize} size='lg'>
            Authorize
          </Button>
        </Flex>
      </Box>
    );
  }

  // If we get here, user is not signed in and we're in initial redirect
  return (
    <Box
      maxW='container.sm'
      mx='auto'
      py={10}
      px={4}
      textAlign='center'
      color='white'
    >
      <Heading as='h1' size='xl' mb={6}>
        Linking Your Suno Account
      </Heading>
      <Text fontSize='lg'>Redirecting to sign in...</Text>
    </Box>
  );
}
