import { useCallback, useEffect, useMemo, useState } from 'react';

import { JwtPayload, RESTConfig } from '@/back-api';
import { PartRight } from '@/back-api/model/part-right';
import { environment, getApiUrl } from '@/environment';
import { useServiceContext } from '@/service/ServiceContext';
import { isBrowser } from '@/utils/layout';
import { parseToken } from '@/utils/sso';
import { createListCollection } from '@chakra-ui/react';

const TOKEN_KEY = 'karideo-token-key-storage';

export const USERS_COLLECTION = createListCollection({
  items: [
    { label: "admin", value: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E" },
    { label: "NO_USER", value: "svelte" },
  ],
})
export const USERS = {
  admin:
    'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwiYXBwbGljYXRpb24iOiJrYXJ1c2ljIiwiaXNzIjoiS2FyQXV0aCIsInJpZ2h0Ijp7ImthcnVzaWMiOnsiQURNSU4iOnRydWUsIlVTRVIiOnRydWV9fSwibG9naW4iOiJIZWVyb1l1aSIsImV4cCI6MTcyNDIwNjc5NCwiaWF0IjoxNzI0MTY2ODM0fQ.TEST_SIGNATURE_FOR_LOCAL_TEST_AND_TEST_E2E',
  NO_USER: '',
} as const;

export const getUserToken = () => {
  return localStorage.getItem(TOKEN_KEY);
};
export type RightGroup = 'ADMIN' | 'USER';

export function getRestConfig(): RESTConfig {
  return {
    server: getApiUrl(),
    token: getUserToken() ?? '',
  };
}

export type SessionServiceProps = {
  token?: string;
  isConnected: boolean;
  setToken: (token: string) => void;
  clearToken: () => void;
  login?: string;
  hasReadRight: (part: RightGroup) => boolean;
  hasWriteRight: (part: RightGroup) => boolean;
  getRestConfig: () => RESTConfig;
};

export const useSessionService = (): SessionServiceProps => {
  const { session } = useServiceContext();
  return session;
};

export const useSessionServiceWrapped = (): SessionServiceProps => {
  const [token, setToken] = useState<string | undefined>(
    isBrowser ? (localStorage.getItem(TOKEN_KEY) ?? undefined) : undefined
  );
  const [config, setConfig] = useState<JwtPayload | undefined>(undefined);

  const updateRight = useCallback(() => {

    console.log('Detect a new token...');
    setConfig(undefined);
    if (token === undefined) {
      console.log(`  ==> No User`);
      localStorage.removeItem(TOKEN_KEY);
    } else {
      const dataParsedToken = parseToken(token)?.payload;
      console.log(`Get right: ${JSON.stringify(dataParsedToken, null, 2)}`);
      setConfig(dataParsedToken);
      console.log('  ==> Login ... (try to keep right)');
      if (isBrowser) {
        localStorage.setItem(TOKEN_KEY, token);
      }
    }
  }, [localStorage, parseToken, token]);
  const setTokenLocal = useCallback(
    (token: string) => {
      setToken(token);
      updateRight();
    },
    [updateRight, setToken]
  );
  const clearToken = useCallback(() => {
    console.log('Clear Token');
    setToken(undefined);
    updateRight();
  }, [updateRight, setToken]);
  const hasReadRight = useCallback(
    (group: RightGroup) => {
      if (token === undefined) {
        return false;
      }
      const right = config?.right[environment.applName];
      if (right === undefined) {
        return false;
      }
      return [PartRight.READ, PartRight.READ_WRITE].includes(
        right?.[group] ?? 0
      );
    },
    [config]
  );
  const hasWriteRight = useCallback(
    (group: RightGroup) => {
      if (token === undefined) {
        return false;
      }
      const right = config?.right[environment.applName];
      if (right === undefined) {
        return false;
      }
      return [PartRight.READ, PartRight.READ_WRITE].includes(
        right?.[group] ?? 0
      );
    },
    [config]
  );

  const getRestConfig = useCallback((): RESTConfig => {
    return {
      server: getApiUrl(),
      token: token ?? '',
    };
  }, [token]);

  useEffect(() => {
    updateRight();
  }, [updateRight]);

  return {
    token,
    isConnected: token !== undefined,
    setToken: setTokenLocal,
    clearToken,
    login: config?.login,
    hasReadRight,
    hasWriteRight,
    getRestConfig,
  };
};

export const useHasRight = (group: RightGroup) => {
  const { token, hasReadRight, hasWriteRight } = useSessionService();
  const isReadable = useMemo(() => {
    console.log(`get is read for: ${group} ==> ${hasReadRight(group)}`);
    return hasReadRight(group);
  }, [token, hasReadRight, group]);
  const isWritable = useMemo(() => {
    return hasWriteRight(group);
  }, [token, hasWriteRight, group]);
  return { isReadable, isWritable };
};
