import { createContext, use, useMemo, useState, useEffect } from 'react';
import { SessionContext } from '@arcblock/did-connect-react/lib/Session';

import type { SessionContext as TSessionContext, Session } from '../@types';

export interface SpaceGateway {
  did: string;
  name: string;
  url: string;
  endpoint: string;
}

export interface SettingStorageEndpoint {
  (endpoint: string | undefined): void | Promise<void>;
}

interface ConfigUserSpaceContextType {
  loading: boolean;
  spaceGateway: SpaceGateway | undefined;
  session: Session;
  deleteSpaceGateway: (spaceGateway: SpaceGateway) => Promise<void>;
  updateSpaceGateway: (updateSpaceGateway: SpaceGateway) => Promise<void>;
  storageEndpoint: string;
  settingStorageEndpoint: SettingStorageEndpoint;
  hasStorageEndpoint: boolean;
}

const ConfigUserSpaceContext = createContext<ConfigUserSpaceContextType>({} as ConfigUserSpaceContextType);
const { Provider, Consumer } = ConfigUserSpaceContext;

function ConfigUserSpaceProvider({ children }: { children: React.ReactNode }) {
  const [loading] = useState(false);
  const { session } = use<TSessionContext>(SessionContext);
  const { user } = session;

  const [spaceGateway, setSpaceGateway] = useState<SpaceGateway | undefined>();
  const storageEndpoint = useMemo(() => {
    return user?.didSpace?.endpoint;
  }, [user?.didSpace]);

  useEffect(() => {
    setSpaceGateway(user?.didSpace as SpaceGateway);
  }, [user?.didSpace]);

  // eslint-disable-next-line require-await
  const deleteSpaceGateway = async (): Promise<void> => {
    setSpaceGateway(undefined);
  };

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const settingStorageEndpoint = (endpoint: string | undefined) => {};

  const updateSpaceGateway = async (x: SpaceGateway) => {
    setSpaceGateway(x);
    // eslint-disable-next-line no-use-before-define
    await settingStorageEndpoint(x.endpoint);
  };

  const hasStorageEndpoint = Boolean(storageEndpoint && spaceGateway);

  return (
    <Provider
      value={{
        loading,
        spaceGateway,
        session,
        deleteSpaceGateway,
        updateSpaceGateway,
        storageEndpoint,
        settingStorageEndpoint,
        hasStorageEndpoint,
      }}>
      {children}
    </Provider>
  );
}

function useConfigUserSpaceContext() {
  const res = use(ConfigUserSpaceContext);
  return res;
}

export {
  ConfigUserSpaceContext,
  ConfigUserSpaceProvider,
  Consumer as ConfigUserSpaceConsumer,
  useConfigUserSpaceContext,
};
