'use client'

import { Avatar } from '@langgenius/dify-ui/avatar'
import { Button } from '@langgenius/dify-ui/button'
import { toast } from '@langgenius/dify-ui/toast'
import {
  RiAccountCircleLine,
  RiGlobalLine,
  RiInfoCardLine,
  RiMailLine,
  RiTranslate2,
} from '@remixicon/react'
import { useQuery } from '@tanstack/react-query'
import * as React from 'react'
import { useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import Loading from '@/app/components/base/loading'
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { isLegacyBase401, userProfileQueryOptions } from '@/features/account-profile/client'
import { useRouter, useSearchParams } from '@/next/navigation'
import { useLogout } from '@/service/use-common'
import { useAuthorizeOAuthApp, useOAuthAppInfo } from '@/service/use-oauth'

function buildReturnUrl(pathname: string, search: string) {
  try {
    const base = `${globalThis.location.origin}${pathname}${search}`
    return base
  }
  catch {
    return pathname + search
  }
}

export default function OAuthAuthorize() {
  const { t } = useTranslation()

  const SCOPE_INFO_MAP: Record<string, { icon: React.ComponentType<{ className?: string }>, label: string }> = {
    'read:name': {
      icon: RiInfoCardLine,
      label: t('scopes.name', { ns: 'oauth' }),
    },
    'read:email': {
      icon: RiMailLine,
      label: t('scopes.email', { ns: 'oauth' }),
    },
    'read:avatar': {
      icon: RiAccountCircleLine,
      label: t('scopes.avatar', { ns: 'oauth' }),
    },
    'read:interface_language': {
      icon: RiTranslate2,
      label: t('scopes.languagePreference', { ns: 'oauth' }),
    },
    'read:timezone': {
      icon: RiGlobalLine,
      label: t('scopes.timezone', { ns: 'oauth' }),
    },
  }

  const router = useRouter()
  const language = useLanguage()
  const searchParams = useSearchParams()
  const client_id = decodeURIComponent(searchParams.get('client_id') || '')
  const redirect_uri = decodeURIComponent(searchParams.get('redirect_uri') || '')
  // Probe user profile. 401 stays as `error` (legitimate "not logged in" state),
  // other errors throw to the nearest error.tsx; jumpTo same-pathname guard in
  // service/base.ts prevents a redirect loop here.
  const { data: userProfileResp, isPending: isProfileLoading, error: profileError } = useQuery({
    ...userProfileQueryOptions(),
    throwOnError: err => !isLegacyBase401(err),
  })
  const isLoggedIn = !!userProfileResp && !profileError
  const userProfile = userProfileResp?.profile
  const { data: authAppInfo, isLoading: isOAuthLoading, isError } = useOAuthAppInfo(client_id, redirect_uri)
  const { mutateAsync: authorize, isPending: authorizing } = useAuthorizeOAuthApp()
  const { mutateAsync: logout } = useLogout()
  const hasNotifiedRef = useRef(false)

  const isLoading = isOAuthLoading || isProfileLoading
  const onLoginSwitchClick = async () => {
    try {
      const returnUrl = buildReturnUrl('/account/oauth/authorize', `?${searchParams.toString()}`)
      if (isLoggedIn)
        await logout()
      router.push(`/signin?redirect_url=${encodeURIComponent(returnUrl)}`)
    }
    catch {
      router.push('/signin')
    }
  }

  const onAuthorize = async () => {
    if (!client_id || !redirect_uri)
      return
    try {
      const { code } = await authorize({ client_id })
      const url = new URL(redirect_uri)
      url.searchParams.set('code', code)
      globalThis.location.href = url.toString()
    }
    catch (err: any) {
      toast.error(`${t('error.authorizeFailed', { ns: 'oauth' })}: ${err.message}`)
    }
  }

  useEffect(() => {
    const invalidParams = !client_id || !redirect_uri
    if ((invalidParams || isError) && !hasNotifiedRef.current) {
      hasNotifiedRef.current = true
      toast.error(
        invalidParams ? t('error.invalidParams', { ns: 'oauth' }) : t('error.authAppInfoFetchFailed', { ns: 'oauth' }),
        { timeout: 0 },
      )
    }
  }, [client_id, redirect_uri, isError])

  if (isLoading) {
    return (
      <div className="bg-background-default-subtle">
        <Loading type="app" />
      </div>
    )
  }

  return (
    <div className="bg-background-default-subtle">
      {authAppInfo?.app_icon && (
        <div className="w-max rounded-2xl border-[0.5px] border-components-panel-border bg-text-primary-on-surface p-3 shadow-lg">
          <img src={authAppInfo.app_icon} alt="app icon" className="size-10 rounded-sm" />
        </div>
      )}

      <div className={`mt-5 mb-4 flex flex-col gap-2 ${isLoggedIn ? 'pb-2' : ''}`}>
        <div className="title-4xl-semi-bold">
          {isLoggedIn && <div className="text-text-primary">{t('connect', { ns: 'oauth' })}</div>}
          <div className="text-saas-dify-blue-inverted">{authAppInfo?.app_label[language] || authAppInfo?.app_label?.en_US || t('unknownApp', { ns: 'oauth' })}</div>
          {!isLoggedIn && <div className="text-text-primary">{t('tips.notLoggedIn', { ns: 'oauth' })}</div>}
        </div>
        <div className="body-md-regular text-text-secondary">{isLoggedIn ? `${authAppInfo?.app_label[language] || authAppInfo?.app_label?.en_US || t('unknownApp', { ns: 'oauth' })} ${t('tips.loggedIn', { ns: 'oauth' })}` : t('tips.needLogin', { ns: 'oauth' })}</div>
      </div>

      {isLoggedIn && userProfile && (
        <div className="flex items-center justify-between rounded-xl bg-background-section-burn-inverted p-3">
          <div className="flex items-center gap-2.5">
            <Avatar avatar={userProfile.avatar_url} name={userProfile.name} size="lg" />
            <div>
              <div className="system-md-semi-bold text-text-secondary">{userProfile.name}</div>
              <div className="system-xs-regular text-text-tertiary">{userProfile.email}</div>
            </div>
          </div>
          <Button variant="tertiary" size="small" onClick={onLoginSwitchClick}>{t('switchAccount', { ns: 'oauth' })}</Button>
        </div>
      )}

      {isLoggedIn && Boolean(authAppInfo?.scope) && (
        <div className="mt-2 flex flex-col gap-2.5 rounded-xl bg-background-section-burn-inverted px-[22px] py-5 text-text-secondary">
          {authAppInfo!.scope.split(/\s+/).filter(Boolean).map((scope: string) => {
            const Icon = SCOPE_INFO_MAP[scope]
            return (
              <div key={scope} className="flex items-center gap-2 body-sm-medium text-text-secondary">
                {Icon ? <Icon.icon className="size-4" /> : <RiAccountCircleLine className="size-4" />}
                {Icon!.label}
              </div>
            )
          })}
        </div>
      )}

      <div className="flex flex-col items-center gap-2 pt-4">
        {!isLoggedIn
          ? (
              <Button variant="primary" size="large" className="w-full" onClick={onLoginSwitchClick}>{t('login', { ns: 'oauth' })}</Button>
            )
          : (
              <>
                <Button variant="primary" size="large" className="w-full" onClick={onAuthorize} disabled={!client_id || !redirect_uri || isError || authorizing} loading={authorizing}>{t('continue', { ns: 'oauth' })}</Button>
                <Button size="large" className="w-full" onClick={() => router.push('/apps')}>{t('operation.cancel', { ns: 'common' })}</Button>
              </>
            )}
      </div>
      <div className="mt-4 py-2">
        <svg xmlns="http://www.w3.org/2000/svg" width="400" height="1" viewBox="0 0 400 1" fill="none">
          <path d="M0 0.5H400" stroke="url(#paint0_linear_2_5904)" />
          <defs>
            <linearGradient id="paint0_linear_2_5904" x1="400" y1="9.49584" x2="0.000228929" y2="9.17666" gradientUnits="userSpaceOnUse">
              <stop stop-color="white" stop-opacity="0.01" />
              <stop offset="0.505" stop-color="#101828" stop-opacity="0.08" />
              <stop offset="1" stop-color="white" stop-opacity="0.01" />
            </linearGradient>
          </defs>
        </svg>
      </div>
      <div className="mt-3 system-xs-regular text-text-tertiary">{t('tips.common', { ns: 'oauth' })}</div>
    </div>
  )
}
