import { useMemo } from 'react';
import {
  ILoginFlow,
  IPasswordFlow,
  ISSOFlow,
  LoginFlow,
  OAUTH_AWARE_PREFERRED_FLOW_FIELD,
} from 'matrix-js-sdk/lib/@types/auth';

export const getSSOFlow = (loginFlows: LoginFlow[]): ISSOFlow | undefined =>
  loginFlows.find((flow) => flow.type === 'm.login.sso' || flow.type === 'm.login.cas') as
    | ISSOFlow
    | undefined;

export const getPasswordFlow = (loginFlows: LoginFlow[]): IPasswordFlow | undefined =>
  loginFlows.find((flow) => flow.type === 'm.login.password') as IPasswordFlow;
export const getTokenFlow = (loginFlows: LoginFlow[]): LoginFlow | undefined =>
  loginFlows.find((flow) => flow.type === 'm.login.token') as ILoginFlow & {
    type: 'm.login.token';
  };

/**
 * MSC3824: a server may advertise `m.login.sso` while signalling (via the
 * `oauth_aware_preferred` / `org.matrix.msc3824.delegated_oidc_compatibility`
 * flow field) that it actually prefers native OIDC. This is a *secondary* hint —
 * the authoritative signal for next-gen auth is an issuer in `.well-known`
 * discovery (see `getOidcIssuer` in cs-api.ts).
 */
export const getOidcCompatibilityFlag = (loginFlows: LoginFlow[]): boolean => {
  const sso = getSSOFlow(loginFlows) as (ISSOFlow & Record<string, unknown>) | undefined;
  if (!sso) return false;
  return (
    sso[OAUTH_AWARE_PREFERRED_FLOW_FIELD.name] === true ||
    sso[OAUTH_AWARE_PREFERRED_FLOW_FIELD.altName] === true
  );
};

export type ParsedLoginFlows = {
  password?: LoginFlow;
  token?: LoginFlow;
  sso?: ISSOFlow;
};
export const useParsedLoginFlows = (loginFlows: LoginFlow[]) => {
  const parsedFlow: ParsedLoginFlows = useMemo<ParsedLoginFlows>(
    () => ({
      password: getPasswordFlow(loginFlows),
      token: getTokenFlow(loginFlows),
      sso: getSSOFlow(loginFlows),
    }),
    [loginFlows],
  );

  return parsedFlow;
};
