/* 
 * This file is part of Stack Wallet.
 * 
 * Copyright (c) 2023 Cypher Stack
 * All Rights Reserved.
 * The code is distributed under GPLv3 license, see LICENSE file for details.
 * Generated by Cypher Stack on 2023-05-26
 *
 */

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../models/isar/models/ethereum/eth_contract.dart';
import '../pages/token_view/token_view.dart';
import '../pages/wallet_view/wallet_view.dart';
import '../pages_desktop_specific/my_stack_view/wallet_view/desktop_token_view.dart';
import '../pages_desktop_specific/my_stack_view/wallet_view/desktop_wallet_view.dart';
import '../providers/db/main_db_provider.dart';
import '../providers/providers.dart';
import '../utilities/constants.dart';
import '../utilities/logger.dart';
import '../utilities/show_loading.dart';
import '../utilities/util.dart';
import '../wallets/isar/providers/eth/current_token_wallet_provider.dart';
import '../wallets/wallet/impl/ethereum_wallet.dart';
import '../wallets/wallet/impl/sub_wallets/eth_token_wallet.dart';
import '../wallets/wallet/wallet.dart';
import '../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
import 'conditional_parent.dart';
import 'desktop/primary_button.dart';
import 'dialogs/basic_dialog.dart';
import 'rounded_white_container.dart';
import 'wallet_info_row/wallet_info_row.dart';

class SimpleWalletCard extends ConsumerWidget {
  const SimpleWalletCard({
    super.key,
    required this.walletId,
    this.contractAddress,
    this.popPrevious = false,
    this.desktopNavigatorState,
  });

  final String walletId;
  final String? contractAddress;
  final bool popPrevious;
  final NavigatorState? desktopNavigatorState;

  Future<bool> _loadTokenWallet(
    BuildContext context,
    WidgetRef ref,
    Wallet wallet,
    EthContract contract,
  ) async {
    final old = ref.read(tokenServiceStateProvider);
    // exit previous if there is one
    unawaited(old?.exit());
    ref.read(tokenServiceStateProvider.state).state = Wallet.loadTokenWallet(
      ethWallet: wallet as EthereumWallet,
      contract: contract,
    ) as EthTokenWallet;

    try {
      await ref.read(pCurrentTokenWallet)!.init();
      return true;
    } catch (_) {
      await showDialog<void>(
        barrierDismissible: false,
        context: context,
        builder: (context) => BasicDialog(
          title: "Failed to load token data",
          desktopHeight: double.infinity,
          desktopWidth: 450,
          rightButton: PrimaryButton(
            label: "OK",
            onPressed: () {
              Navigator.of(context).pop();
              Navigator.of(context).pop();
              if (desktopNavigatorState == null) {
                Navigator.of(context).pop();
              }
            },
          ),
        ),
      );
      return false;
    }
  }

  void _openWallet(BuildContext context, WidgetRef ref) async {
    final nav = Navigator.of(context);

    final wallet = ref.read(pWallets).getWallet(walletId);

    if (context.mounted) {
      final Future<void> loadFuture;
      if (wallet is CwBasedInterface) {
        loadFuture = wallet.init().then((value) async => await (wallet).open());
      } else {
        loadFuture = wallet.init();
      }
      await showLoading(
        whileFuture: loadFuture,
        context: context,
        message: 'Opening ${wallet.info.name}',
        rootNavigator: Util.isDesktop,
      );
      if (popPrevious) nav.pop();

      if (desktopNavigatorState != null) {
        unawaited(
          desktopNavigatorState!.pushNamed(
            DesktopWalletView.routeName,
            arguments: walletId,
          ),
        );
      } else {
        unawaited(
          nav.pushNamed(
            WalletView.routeName,
            arguments: walletId,
          ),
        );
      }

      if (contractAddress != null) {
        final contract =
            ref.read(mainDBProvider).getEthContractSync(contractAddress!)!;

        final success = await showLoading<bool>(
          whileFuture: _loadTokenWallet(
            desktopNavigatorState?.context ?? context,
            ref,
            wallet,
            contract,
          ),
          context: desktopNavigatorState?.context ?? context,
          opaqueBG: true,
          message: "Loading ${contract.name}",
          rootNavigator: Util.isDesktop,
        );

        if (!success!) {
          // TODO: show error dialog here?
          Logging.instance.log(
            "Failed to load token wallet for $contract",
            level: LogLevel.Error,
          );
          return;
        }

        if (desktopNavigatorState != null) {
          await desktopNavigatorState!.pushNamed(
            DesktopTokenView.routeName,
            arguments: walletId,
          );
        } else {
          await nav.pushNamed(
            TokenView.routeName,
            arguments: (walletId: walletId, popPrevious: !Util.isDesktop),
          );
        }
      }
    }
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return ConditionalParent(
      condition: !Util.isDesktop,
      builder: (child) => RoundedWhiteContainer(
        padding: const EdgeInsets.all(0),
        child: MaterialButton(
          // splashColor: Theme.of(context).extension<StackColors>()!.highlight,
          key: Key("walletsSheetItemButtonKey_$walletId"),
          padding: const EdgeInsets.all(10),
          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(
              Constants.size.circularBorderRadius,
            ),
          ),
          onPressed: () => _openWallet(context, ref),
          child: child,
        ),
      ),
      child: WalletInfoRow(
        walletId: walletId,
        contractAddress: contractAddress,
        onPressedDesktop:
            Util.isDesktop ? () => _openWallet(context, ref) : null,
      ),
    );
  }
}