import { normalizeNextPath } from './next-path'
import { PASSWORD_POLICY_HINT, PASSWORD_POLICY_PLACEHOLDER, validateStrongPassword } from './password-policy'
import {
  isGitHubOAuthEnabled,
  isGoogleOAuthEnabled,
  isOrcidOAuthEnabled,
  isSuperTokensConfigured,
  SUPERTOKENS_API_BASE_PATH,
  SUPERTOKENS_API_DOMAIN,
  SUPERTOKENS_WEBSITE_BASE_PATH,
  SUPERTOKENS_WEBSITE_DOMAIN,
} from './supertokens-runtime'

let initialized = false
let initPromise: Promise<void> | null = null

function readRequestedPostAuthPath() {
  if (typeof window === 'undefined') return null
  const params = new URLSearchParams(window.location.search)
  return normalizeNextPath(params.get('next'), '') || null
}

const SUPERTOKENS_BRAND_STYLE = `
[data-supertokens~="container"] {
  --palette-background: 11, 16, 32;
  --palette-inputBackground: 16, 22, 44;
  --palette-inputBorder: 84, 203, 255;
  --palette-primary: 247, 178, 103;
  --palette-primaryBorder: 247, 178, 103;
  --palette-success: 158, 255, 199;
  --palette-successBackground: 10, 62, 47;
  --palette-error: 248, 113, 113;
  --palette-errorBackground: 69, 10, 10;
  --palette-textTitle: 244, 246, 248;
  --palette-textLabel: 212, 225, 245;
  --palette-textInput: 247, 249, 252;
  --palette-textPrimary: 247, 178, 103;
  --palette-textLink: 84, 203, 255;
  --palette-buttonText: 11, 16, 32;
  --palette-superTokensBrandingBackground: 11, 16, 32;
  --palette-superTokensBrandingText: 212, 225, 245;
  width: min(460px, calc(100vw - 2rem));
  margin-top: 0;
  border: 1px solid rgba(84, 203, 255, 0.24) !important;
  border-radius: 24px !important;
  background: rgba(12, 18, 35, 0.94) !important;
  box-shadow: 0 28px 90px rgba(0, 0, 0, 0.55) !important;
}
[data-supertokens~="button"] {
  min-height: 44px;
  border-radius: 999px !important;
  background: #f7b267 !important;
  border-color: #f7b267 !important;
  color: #0b1020 !important;
  font-weight: 700;
}
[data-supertokens~="button"]:hover {
  background: #ffc788 !important;
}
[data-supertokens~="inputWrapper"] {
  min-height: 44px;
  border-radius: 14px !important;
  background: rgba(14, 21, 40, 0.92) !important;
  border: 1px solid rgba(84, 203, 255, 0.28) !important;
  color: #f8fafc !important;
}
`

type SuperTokensAuthResponse = {
  status?: string
  formFields?: Array<{ error?: string }>
}

type SuperTokensFormField = {
  id: string
  value: string
}

type SuperTokensFormInput = {
  formFields: SuperTokensFormField[]
}

type SuperTokensThirdPartyId = 'github' | 'google' | 'orcid'

type SuperTokensCustomProviderConfig = {
  id: string
  name: string
}

type BuiltInProviderFactory<TProvider> = {
  init: () => TProvider
}

export function buildEnabledThirdPartyProviders<TProvider>({
  githubEnabled,
  googleEnabled,
  orcidEnabled,
  Github,
  Google,
}: {
  githubEnabled: boolean
  googleEnabled: boolean
  orcidEnabled: boolean
  Github: BuiltInProviderFactory<TProvider>
  Google: BuiltInProviderFactory<TProvider>
}) {
  const thirdPartyProviders: Array<TProvider | SuperTokensCustomProviderConfig> = []

  if (githubEnabled) thirdPartyProviders.push(Github.init())
  if (googleEnabled) thirdPartyProviders.push(Google.init())
  if (orcidEnabled) {
    thirdPartyProviders.push({
      id: 'orcid',
      name: 'ORCID',
    })
  }

  return thirdPartyProviders
}

export async function ensureSuperTokensInit() {
  if (initialized || !isSuperTokensConfigured() || typeof window === 'undefined') {
    return
  }

  if (!initPromise) {
    initPromise = (async () => {
      const [
        { default: SuperTokens },
        { default: EmailPassword },
        thirdPartyModule,
        { default: Session },
      ] = await Promise.all([
        import('supertokens-auth-react'),
        import('supertokens-auth-react/recipe/emailpassword'),
        import('supertokens-auth-react/recipe/thirdparty'),
        import('supertokens-auth-react/recipe/session'),
      ])

      const { default: ThirdParty, Github, Google } = thirdPartyModule

      const thirdPartyProviders = buildEnabledThirdPartyProviders({
        githubEnabled: isGitHubOAuthEnabled(),
        googleEnabled: isGoogleOAuthEnabled(),
        orcidEnabled: isOrcidOAuthEnabled(),
        Github,
        Google,
      })

      const recipeList: Parameters<typeof SuperTokens.init>[0]['recipeList'] = [
        EmailPassword.init({
          signInAndUpFeature: {
            signInForm: {
              formFields: [
                { id: 'email', label: 'Email', placeholder: 'operator@hypertwist.app' },
                { id: 'password', label: 'Password', placeholder: 'Your password' },
              ],
            },
            signUpForm: {
              formFields: [
                { id: 'email', label: 'Email', placeholder: 'operator@hypertwist.app' },
                {
                  id: 'password',
                  label: `Password (${PASSWORD_POLICY_HINT})`,
                  placeholder: PASSWORD_POLICY_PLACEHOLDER,
                  validate: async (value: unknown) => validateStrongPassword(String(value || '')),
                },
              ],
            },
          },
        }),
        Session.init(),
      ]

      if (thirdPartyProviders.length > 0) {
        recipeList.splice(1, 0, ThirdParty.init({
          signInAndUpFeature: {
            providers: thirdPartyProviders,
          },
        }))
      }

      SuperTokens.init({
        appInfo: {
          appName: 'HyperTwist',
          apiDomain: SUPERTOKENS_API_DOMAIN,
          websiteDomain: SUPERTOKENS_WEBSITE_DOMAIN || window.location.origin,
          apiBasePath: SUPERTOKENS_API_BASE_PATH,
          websiteBasePath: SUPERTOKENS_WEBSITE_BASE_PATH,
        },
        recipeList,
        style: SUPERTOKENS_BRAND_STYLE,
        getRedirectionURL: async (context) => {
          if (context.action === 'SUCCESS') {
            return readRequestedPostAuthPath() || '/app'
          }
          return undefined
        },
      })

      initialized = true
    })().finally(() => {
      if (!initialized) {
        initPromise = null
      }
    })
  }

  await initPromise
}

export async function signInWithSuperTokens(input: SuperTokensFormInput) {
  await ensureSuperTokensInit()
  const { signIn } = await import('supertokens-auth-react/recipe/emailpassword')
  return signIn(input) as Promise<SuperTokensAuthResponse>
}

export async function signUpWithSuperTokens(input: SuperTokensFormInput) {
  await ensureSuperTokensInit()
  const { signUp } = await import('supertokens-auth-react/recipe/emailpassword')
  return signUp(input) as Promise<SuperTokensAuthResponse>
}

export async function redirectToSuperTokensThirdPartyLogin(thirdPartyId: SuperTokensThirdPartyId) {
  await ensureSuperTokensInit()
  const { redirectToThirdPartyLogin } = await import('supertokens-auth-react/recipe/thirdparty')
  await redirectToThirdPartyLogin({ thirdPartyId })
}

export async function signOutFromSuperTokens() {
  await ensureSuperTokensInit()
  const { signOut } = await import('supertokens-auth-react/recipe/session')
  await signOut()
}
