import { code } from 'dashboard/generated/controlplane';
import { createServices } from 'dashboard/generated/controlplane/twirp';
import * as _ from 'lodash';
import { useEffect, useState } from 'react';
import { GetControlplaneEndpoint } from './env';

export interface CurrentUser {
  user: string;
  loading: boolean;
  errored: boolean;
}

let currentUserCache: string;

export async function getCurrentUser(): Promise<string> {
  if (currentUserCache) {
    return currentUserCache;
  }

  try {
    const ldapUser = await (await fetch('/api/current-user')).json();
    currentUserCache = ldapUser;
    return ldapUser;
  } catch (err) {
    return '';
  }
}

export const useCurrentUser = (): CurrentUser => {
  if (currentUserCache) {
    return { user: currentUserCache, loading: false, errored: false };
  }

  const [loading, setLoading] = useState(true);
  const [errored, setErrored] = useState(false);
  const [user, setUser] = useState('');

  useEffect(() => {
    const fetchUser = async () => {
      setLoading(true);
      setErrored(false);

      try {
        const resp = await fetch('/api/current-user');
        const fetchedUser = await resp.json();
        setLoading(false);
        setErrored(false);
        setUser(fetchedUser);
      } catch {
        setLoading(false);
        setErrored(true);
      }
    };
    fetchUser();
  }, []);

  return { user, loading, errored };
};

export const useLDAPGroups = () => {
  const [ldapGroups, setLdapGroups] = useState(new Array<string>());
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const client = createServices(GetControlplaneEndpoint());

  useEffect(() => {
    const fetchData = async () => {
      try {
        const requestorLDAPGroupsReq = new code.justin.tv.eventbus.controlplane.RequestorLDAPGroupsReq(
          {},
        );
        const res = await client.requestorLDAPGroups(requestorLDAPGroupsReq);
        const groups = res.ldapGroups || new Array<string>();
        setLdapGroups(groups);
        setLoading(false);
      } catch (err) {
        setError(err);
        setLoading(false);
      }
    };
    fetchData();
  }, []);

  return { ldapGroups, loading, error };
};

export const useLDAPGroupMembers = (ldapGroup: string) => {
  const [ldapGroupMembers, setLDAPGroupMembers] = useState(new Array<string>());
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);

  const client = createServices(GetControlplaneEndpoint());

  useEffect(() => {
    const fetchData = async () => {
      try {
        const resolveLDAPGroupUsersReq = new code.justin.tv.eventbus.controlplane.ResolveLDAPGroupUsersReq(
          {
            ldapGroup,
          },
        );
        const res = await client.resolveLDAPGroupUsers(
          resolveLDAPGroupUsersReq,
        );
        const entries = res.ldapEntries || new Array<string>();
        setLDAPGroupMembers(_.map(entries, (e) => e.commonName!));
        setLoading(false);
      } catch (err) {
        setError(err);
        setLoading(false);
      }
    };
    fetchData();
  }, []);

  return {
    ldapGroupMembers,
    loading,
    error,
  };
};
