import api from 'src/config/api';
import { encryptStorage } from 'src/config/encrypt-storage';
import { type CommunityFeature } from 'src/types/communityFeatures';
import { type FeatureFlag } from 'src/types/featureFlags';
import { type Instance } from 'src/types/instance';
import {
  type AuthResponse,
  type AzureLoginData,
  type GoogleLoginData,
  type IdpProvidersResponse,
  type InitMFAResponse,
  type JanusMeRawResponse,
  type LoginData,
  type LoginInstance,
  type LoginOTPData,
  type LoginResponse,
  type OAuth2IdpInitiatedRequest,
  type OAuth2IdpInitiatedResponse,
  type OktaLoginData,
  type OTP,
  type SendOTPData,
  type UpdatePasswordWithCodeData,
} from 'src/types/login';
import { type Terms } from 'src/types/terms';

export const getInstances = (params: { username: string }) =>
  api.get<LoginInstance[]>('janus/auth/instances', {
    params,
    skipInterceptor: true,
  }); // instances for auth (e.g. login/select), no token yet

export const getOTP = (instanceId: number, employeeInternalId: string) =>
  api.get<OTP[]>('auth/otp', {
    params: {
      instanceId,
      employeeInternalId,
    },
    skipInterceptor: true, // OTP flow (send/login), code in body
  });

export const sendOTP = (sendOTPData: SendOTPData) =>
  api.post('auth/otp/send', sendOTPData, { skipInterceptor: true }); // OTP flow (send/login), code in body

export const loginOTP = (loginOTPData: LoginOTPData) =>
  api.post<AuthResponse>('auth/otp/login', loginOTPData, {
    withCredentials: true,
    skipInterceptor: true, // OTP flow (send/login), code in body
  });

export const initiate2FA = (loginData: LoginData) =>
  api.post<InitMFAResponse>('auth/otp/init-2fa', loginData, {
    withCredentials: true,
    skipInterceptor: true, // OTP flow (send/login), code in body
  });

export const login = (loginData: LoginData) =>
  api.post<LoginResponse>('auth/login', loginData, {
    withCredentials: true,
    skipInterceptor: true, // login, no token yet
  });

export const loginViaJanus = (loginData: LoginData) =>
  api.post<AuthResponse>('janus/auth/login', loginData, {
    withCredentials: true,
    skipInterceptor: true, // login, no token yet
  });

export const logout = () =>
  api.post('auth/logout', {
    withCredentials: true,
  });

export const authRefresh = () =>
  api.get<AuthResponse>('/auth/refresh', {
    withCredentials: true,
    headers: {
      Authorization: `Bearer ${encryptStorage.getItem('refreshToken')}`,
    },
    validateStatus: null, // ignore interceptors
    skipInterceptor: true, // caller sets Bearer (refresh token) manually
  });

export const getChildSessions = (refreshToken: string) =>
  api.post<AuthResponse>(
    '/auth/sessions/child',
    {},
    {
      headers: { Authorization: `Bearer ${refreshToken}` },
      skipInterceptor: true, // caller sets refresh token manually
    },
  );

export const getJanusFeatureFlags = () =>
  api.get<{ featureFlags: FeatureFlag }>('janus/feature-flags');

export const getJanusCommunityFeatures = () =>
  api.get<{ communityFeatures: CommunityFeature[] }>(
    'janus/community-features',
  );

export const getJanusMe = () => api.get<JanusMeRawResponse>('janus/me');

export const tokenLogin = (token: string) =>
  api.post<AuthResponse>('users/token-login', undefined, {
    withCredentials: true,
    headers: { Authorization: `Bearer ${token}` },
    skipInterceptor: true, // caller sets token manually
  });

export const azureLogin = (loginData: AzureLoginData) =>
  api.post<AuthResponse>('auth/azure-sso/login', loginData, {
    withCredentials: true,
    skipInterceptor: true, // SSO login, no token yet
  });

export const getAzureInstances = (accessToken: string) =>
  api.post<LoginInstance[]>(
    'auth/azure-sso/instances',
    { accessToken },
    {
      skipInterceptor: true, // instances for SSO, public
    },
  );

export const oktaLogin = (loginData: OktaLoginData) =>
  api.post<AuthResponse>('auth/okta-sso/login', loginData, {
    withCredentials: true,
    skipInterceptor: true, // Okta SSO login
  });

export const getOktaInstances = (accessToken: string) =>
  api.post<LoginInstance[]>(
    'auth/okta-sso/instances',
    { accessToken },
    {
      skipInterceptor: true, // instances for SSO, public
    },
  );

export const getGoogleInstances = (code: string) =>
  api.post<LoginInstance[]>(
    'auth/google-sso/instances',
    { accessToken: code },
    {
      skipInterceptor: true, // instances for SSO, public
    },
  );

export const googleLogin = (loginData: GoogleLoginData) =>
  api.post<LoginResponse>(
    'auth/google-sso/login',
    {
      instanceId: loginData.instanceId,
      accessToken: loginData.accessToken,
    },
    {
      withCredentials: true,
      skipInterceptor: true, // Google SSO login
    },
  );

export const resetPassword = (employeeInternalId: string, instanceId: number) =>
  api.post(
    'auth/reset-password',
    { employeeInternalId, instanceId },
    {
      skipInterceptor: true, // reset request, no token
    },
  );

export const updatePassword = (
  id: number,
  newPassword: string,
  token: string,
) =>
  api.post(
    `users/${id}/update-password`,
    {
      newPassword,
    },
    {
      headers: { Authorization: `Bearer ${token}` },
      skipInterceptor: true, // users/:id/update-password (reset flow, code in body)
    },
  );

export const updatePasswordWithCode = ({
  code,
  passwordInput,
}: UpdatePasswordWithCodeData) =>
  api.post(
    '/auth/update-password',
    {
      code,
      newPassword: passwordInput,
    },
    {
      skipInterceptor: true, // reset flow; token/code in body
    },
  );

export const getIdpProviders = () =>
  api.get<IdpProvidersResponse>('auth/idp/service-providers');

export const initIdpLogin = (appId: number) =>
  api.post(`auth/idp/init/${appId}`);

export const oauth2IdpInitiated = (body: OAuth2IdpInitiatedRequest) =>
  api.post<OAuth2IdpInitiatedResponse>('janus/oauth2/idp-initiated', body); // user JWT injected by interceptor

export const getInstanceForRestorePassword = (code: string) =>
  api.get<Instance>('instances/user-reset-code', {
    params: { code },
    skipInterceptor: true, // reset code
  });

export const getInstanceForRegisterUser = (code: string) =>
  api.get<Instance>('instances/user-code', {
    params: { code },
    skipInterceptor: true, // user code validation
  });

export const getInstanceForJoinByLink = (code: string) =>
  api.get<Instance>('instances/code', {
    params: { code },
    skipInterceptor: true, // instance code (e.g. login)
  });

export const getNewFeatures = () => api.get('/features');

export const getTermsAndConditions = () =>
  api.get<Terms>('/terms-and-conditions');

export const acceptTermsAndConditions = (id: number) =>
  api.post(`/terms-and-conditions/${id}/acceptance`);
