import { CounterValuesState } from "@ledgerhq/live-countervalues/types";
import { CryptoOrTokenCurrency, Currency, Unit } from "@ledgerhq/types-cryptoassets";
import { AccountLike } from "@ledgerhq/types-live";
import type { ComponentType, ReactNode, ReactElement } from "react";
import { EnhancedModularDrawerConfiguration } from "../../wallet-api/ModularDrawer/types";
import { InterestRate } from "../../dada-client/entities";
import { MarketItemResponse } from "../../market/utils/types";
import BigNumber from "bignumber.js";
import { ApyType } from "../../dada-client/types/trend";

export type ApyIndicatorComponent = ComponentType<{ value: number; type: ApyType }>;

export type AssetType = {
  name: string;
  ticker: string;
  id: string;
  leftElement?: ReactNode;
  rightElement?: ReactNode;
};

export type ProviderBalanceAsset = {
  id: string;
  name: string;
  ticker: string;
  balance: string;
  fiatValue: string;
  sortValue: number;
};

export type ProviderBalanceResultsMap = Map<string, ProviderBalanceAsset>;

export type AssetWithBalance = AssetType & {
  sortValue?: number;
};

export type UseBalanceDeps = () => {
  flattenedAccounts: AccountLike[];
  state: CounterValuesState;
  counterValueCurrency: Currency;
  locale: string;
};

export type BalanceUI = {
  // Raw values
  balance: BigNumber;
  fiatValue?: number;
  fiatUnit?: Unit;
  currency: CryptoOrTokenCurrency;
  // Formatting parameters
  locale?: string;
  discreet?: boolean;
};
export type CreateBalanceItem = (x: BalanceUI) => ReactNode;

export type CreateAccountsCountAndApy = (args: {
  label?: string;
  value?: number;
  type?: ApyType;
}) => ReactElement | undefined;

export type NetworkWithCount = {
  leftElement?: ReactNode;
  description?: string;
  apy?: ReactElement;
  count: number;
};

export type AccountDataItem = {
  asset: CryptoOrTokenCurrency;
  label: string;
  count: number;
};

export type AccountModuleParams = {
  networks: CryptoOrTokenCurrency[];
};

export type CreateAccountsCount = (args: { label: string }) => ReactNode;

export type UseAccountData = (params: AccountModuleParams) => AccountDataItem[];

export type NetworkHookParams = {
  networks: CryptoOrTokenCurrency[];
};
// Network hook type that returns additional properties to be merged with currencies
export type NetworkHook = (params: NetworkHookParams) => Array<{
  balanceData?: BalanceUI;
  count?: number;
  leftElement?: ReactNode;
  rightElement?: ReactNode;
  description?: string;
  apy?: ReactElement;
}>;

export type NetworkConfigurationDeps = {
  useAccountData: UseAccountData;
  accountsCount: CreateAccountsCount;
  accountsCountAndApy: CreateAccountsCountAndApy;
  ApyIndicator: ApyIndicatorComponent;
  useBalanceDeps: UseBalanceDeps;
  balanceItem: CreateBalanceItem;
};

export type NetworkLeftElementKind = "numberOfAccounts" | "numberOfAccountsAndApy" | "undefined";
export type NetworkRightElementKind = "balance" | "undefined";

export type Network = {
  name: string;
  id: string;
  ticker: string;
  leftElement?: ReactNode;
  rightElement?: ReactNode;
  description?: string;
  apy?: ReactElement;
};

export type CreateNetworkConfigurationHookProps = {
  networksConfig: EnhancedModularDrawerConfiguration["networks"];
};

export type AssetConfigurationDeps = {
  ApyIndicator: ApyIndicatorComponent;
  MarketPercentIndicator: (args: { percent: number }) => ReactNode;
  MarketPriceIndicator: (args: { price: string; percent: number }) => ReactNode;
  useBalanceDeps: UseBalanceDeps;
  balanceItem: CreateBalanceItem;
  assetsMap: Map<
    string,
    { mainCurrency: CryptoOrTokenCurrency; currencies: CryptoOrTokenCurrency[] }
  >;
};

export type AssetRightElementKind = "balance" | "marketTrend" | "undefined";
export type AssetLeftElementKind = "apy" | "marketTrend" | "undefined";

export type AssetConfigurationOptions = AssetConfigurationDeps & {
  rightElement?: AssetRightElementKind;
  leftElement?: AssetLeftElementKind;
};

export type NetworkConfigurationOptions = NetworkConfigurationDeps & {
  leftElement?: NetworkLeftElementKind;
  rightElement?: NetworkRightElementKind;
};

export type AssetData = {
  asset: {
    id: string;
    ticker: string;
    name: string;
    assetsIds: Record<string, string>;
    metaCurrencyId?: string;
  };
  networks: CryptoOrTokenCurrency[];
  interestRates?: InterestRate;
  market?: Partial<MarketItemResponse>;
};
