import * as plugins from '../plugins.js';
import * as interfaces from '../../ts_interfaces/index.js';
import { appState } from './shared.js';

export interface ILoginState {
  identity: interfaces.data.IIdentity | null;
  isLoggedIn: boolean;
}

export type IAdminBootstrapStatus = interfaces.requests.IReq_GetAdminBootstrapStatus['response'];

export const loginStatePart = await appState.getStatePart<ILoginState>(
  'login',
  {
    identity: null,
    isLoggedIn: false,
  },
  'persistent' // Login state persists across browser sessions
);

// Actions for state management
interface IActionContext {
  identity: interfaces.data.IIdentity | null;
}

export const getActionContext = (): IActionContext => {
  const identity = loginStatePart.getState()!.identity;
  // Treat expired JWTs as no identity — prevents stale persisted sessions from firing requests
  if (identity && identity.expiresAt && identity.expiresAt < Date.now()) {
    return { identity: null };
  }
  return { identity };
};

// Login Action
export const loginAction = loginStatePart.createAction<{
  username: string;
  password: string;
  authSource?: interfaces.requests.TAdminLoginAuthSource;
}>(async (statePartArg, dataArg): Promise<ILoginState> => {
  const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
    interfaces.requests.IReq_AdminLoginWithUsernameAndPassword
  >('/typedrequest', 'adminLoginWithUsernameAndPassword');

  try {
    const response = await typedRequest.fire({
      username: dataArg.username,
      password: dataArg.password,
      authSource: dataArg.authSource,
    });

    if (response.identity) {
      return {
        identity: response.identity,
        isLoggedIn: true,
      };
    }
    return statePartArg.getState()!;
  } catch (error: unknown) {
    console.error('Login failed:', error);
    return statePartArg.getState()!;
  }
});

export async function getAdminBootstrapStatus(): Promise<IAdminBootstrapStatus> {
  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
    interfaces.requests.IReq_GetAdminBootstrapStatus
  >('/typedrequest', 'getAdminBootstrapStatus');

  return request.fire({});
}

export async function createInitialAdminUser(optionsArg: {
  email: string;
  name?: string;
  password: string;
  enableIdpGlobalAuth?: boolean;
}) {
  const context = getActionContext();
  if (!context.identity) {
    throw new Error('No identity available for admin bootstrap');
  }

  const request = new plugins.domtools.plugins.typedrequest.TypedRequest<
    interfaces.requests.IReq_CreateInitialAdminUser
  >('/typedrequest', 'createInitialAdminUser');

  const response = await request.fire({
    identity: context.identity,
    email: optionsArg.email,
    name: optionsArg.name,
    password: optionsArg.password,
    enableIdpGlobalAuth: optionsArg.enableIdpGlobalAuth,
  });

  if (response.identity) {
    loginStatePart.setState({
      identity: response.identity,
      isLoggedIn: true,
    });
  }

  return response;
}

// Logout Action — always clears state, even if identity is expired/missing
export const logoutAction = loginStatePart.createAction(async (statePartArg) => {
  const context = getActionContext();

  // Try to notify server, but don't block logout if identity is missing/expired
  if (context.identity) {
    const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
      interfaces.requests.IReq_AdminLogout
    >('/typedrequest', 'adminLogout');
    try {
      await typedRequest.fire({ identity: context.identity });
    } catch (error) {
      console.error('Logout error:', error);
    }
  }

  // Always clear login state
  return {
    identity: null,
    isLoggedIn: false,
  };
});

