import 'package:flutter/material.dart';

import 'package:go_router/go_router.dart';

import 'package:provider/provider.dart';

import 'package:pshared/controllers/balance_mask/wallets.dart';
import 'package:pshared/models/payment/type.dart';
import 'package:pshared/models/recipient/recipient.dart';
import 'package:pshared/provider/organizations.dart';
import 'package:pshared/provider/payment/amount.dart';
import 'package:pshared/provider/payment/flow.dart';
import 'package:pshared/provider/payment/provider.dart';
import 'package:pshared/provider/payment/quotation/quotation.dart';
import 'package:pshared/provider/recipient/provider.dart';
import 'package:pshared/provider/recipient/methods_cache.dart';
import 'package:pshared/provider/recipient/pmethods.dart';

import 'package:pweb/app/router/pages.dart';
import 'package:pweb/app/router/payout_routes.dart';
import 'package:pweb/providers/quotation/quotation.dart';
import 'package:pshared/models/payment/wallet.dart';
import 'package:pweb/pages/address_book/form/page.dart';
import 'package:pweb/pages/address_book/page/page.dart';
import 'package:pweb/pages/dashboard/dashboard.dart';
import 'package:pweb/pages/invitations/page.dart';
import 'package:pweb/pages/payment_methods/page.dart';
import 'package:pweb/pages/payout_page/wallet/edit/page.dart';
import 'package:pweb/pages/report/page.dart';
import 'package:pweb/pages/settings/profile/page.dart';
import 'package:pweb/pages/wallet_top_up/page.dart';
import 'package:pweb/widgets/dialogs/confirmation_dialog.dart';
import 'package:pweb/widgets/error/snackbar.dart';
import 'package:pweb/widgets/sidebar/destinations.dart';
import 'package:pweb/widgets/sidebar/page.dart';
import 'package:pweb/utils/payment/availability.dart';

import 'package:pweb/generated/i18n/app_localizations.dart';


RouteBase payoutShellRoute() => ShellRoute(
  builder: (context, state, child) => MultiProvider(
    providers: [
      ChangeNotifierProxyProvider2<OrganizationsProvider, RecipientsProvider, PaymentMethodsProvider>(
        create: (_) => PaymentMethodsProvider(),
        update: (context, organizations, recipients, provider) => provider!..updateProviders(organizations, recipients),
      ),
      ChangeNotifierProxyProvider2<OrganizationsProvider, RecipientsProvider, RecipientMethodsCacheProvider>(
        create: (_) => RecipientMethodsCacheProvider(),
        update: (context, organizations, recipients, provider) => provider!..updateProviders(organizations, recipients),
      ),
      ChangeNotifierProxyProvider2<RecipientsProvider, PaymentMethodsProvider, PaymentFlowProvider>(
        create: (_) => PaymentFlowProvider(initialType: enabledPaymentTypes.first),
        update: (context, recipients, methods, provider) => provider!..update(
          recipients,
          methods,
        ),
      ),
      ChangeNotifierProvider(
        create: (_) => PaymentAmountProvider(),
      ),
      ChangeNotifierProxyProvider6<OrganizationsProvider, PaymentAmountProvider, WalletsController, PaymentFlowProvider, RecipientsProvider, PaymentMethodsProvider, QuotationProvider>(
        create: (_) => QuotationProvider(),
        update: (_, organization, payment, wallet, flow, recipients, methods, provider) =>
            provider!..update(organization, payment, wallet, flow, recipients, methods),
      ),
      ChangeNotifierProxyProvider<QuotationProvider, QuotationController>(
        create: (_) => QuotationController(),
        update: (_, quotation, controller) => controller!..update(quotation),
      ),
      ChangeNotifierProxyProvider2<OrganizationsProvider, QuotationProvider, PaymentProvider>(
        create: (_) => PaymentProvider(),
        update: (context, organization, quotation, provider) => provider!..update(
          organization,
          quotation,
        ),
      ),
    ],
    child: PageSelector(
    child: child,
    routerState: state,
  ),
  ),
  routes: [
    GoRoute(
      name: PayoutRoutes.dashboard,
      path: routerPage(Pages.dashboard),
      pageBuilder: (context, _) => NoTransitionPage(
        child: DashboardPage(
          onRecipientSelected: (recipient) => _startPayment(
            context,
            recipient: recipient,
            returnTo: PayoutDestination.dashboard,
          ),
          onGoToPaymentWithoutRecipient: (type) => _startPayment(
            context,
            recipient: null,
            paymentType: type,
            returnTo: PayoutDestination.dashboard,
          ),
          onTopUp: (wallet) => _openWalletTopUp(
            context,
            wallet,
            returnTo: PayoutDestination.dashboard,
          ),
          onWalletTap: (wallet) => _openWalletEdit(
            context,
            wallet,
            returnTo: PayoutDestination.dashboard,
          ),
        ),
      ),
    ),
    GoRoute(
      name: PayoutRoutes.recipients,
      path: PayoutRoutes.recipientsPath,
      pageBuilder: (context, _) {
        final loc = AppLocalizations.of(context)!;
        return NoTransitionPage(
          child: RecipientAddressBookPage(
            onRecipientSelected: (recipient) => _startPayment(
              context,
              recipient: recipient,
              returnTo: PayoutDestination.recipients,
            ),
            onAddRecipient: () => _openAddRecipient(context),
            onEditRecipient: (recipient) =>
                _openAddRecipient(context, recipient: recipient),
            onDeleteRecipient: (recipient) async {
              final confirmed = await showConfirmationDialog(
                context: context,
                title: loc.delete,
                message: loc.deleteRecipientConfirmation,
                confirmLabel: loc.delete,
              );
              if (!confirmed) return;
              await executeActionWithNotification(
              context: context,
              action: () async =>
                  context.read<RecipientsProvider>().delete(recipient.id),
              successMessage: loc.recipientDeletedSuccessfully,
              errorMessage: loc.errorDeleteRecipient,
              );
            },
          ),
        );
      },
    ),
    GoRoute(
      name: PayoutRoutes.invitations,
      path: PayoutRoutes.invitationsPath,
      pageBuilder: (_, _) => const NoTransitionPage(
        child: InvitationsPage(),
      ),
    ),
    GoRoute(
      name: PayoutRoutes.addRecipient,
      path: PayoutRoutes.addRecipientPath,
      pageBuilder: (context, _) {
        final recipient = context.read<RecipientsProvider>().currentObject;
        return NoTransitionPage(
          child: AddressBookRecipientForm(
            recipient: recipient,
            onSaved: (_) => context.goToPayout(PayoutDestination.recipients),
          ),
        );
      },
    ),
    GoRoute(
      name: PayoutRoutes.payment,
      path: PayoutRoutes.paymentPath,
      pageBuilder: (context, state) {
        final fallbackDestination = PayoutRoutes.fallbackFromState(
          state,
          defaultDestination: PayoutDestination.dashboard,
        );

        return NoTransitionPage(
          child: PaymentPage(
            onBack: (_) => _popOrGo(context, fallbackDestination),
            initialPaymentType: PayoutRoutes.paymentTypeFromState(state),
            fallbackDestination: fallbackDestination,
          ),
        );
      },
    ),
    GoRoute(
      name: PayoutRoutes.settings,
      path: PayoutRoutes.settingsPath,
      pageBuilder: (_, _) => const NoTransitionPage(
        child: ProfileSettingsPage(),
      ),
    ),
    GoRoute(
      name: PayoutRoutes.reports,
      path: PayoutRoutes.reportsPath,
      pageBuilder: (_, _) =>
          const NoTransitionPage(child: OperationHistoryPage()),
    ),
    GoRoute(
      name: PayoutRoutes.methods,
      path: PayoutRoutes.methodsPath,
      redirect: (_, state) => PayoutRoutes.dashboardPath,
    ),
    GoRoute(
      name: PayoutRoutes.editWallet,
      path: PayoutRoutes.editWalletPath,
      pageBuilder: (context, state) {
        final walletsProvider = context.read<WalletsController>();
        final wallet = walletsProvider.selectedWallet;
        final loc = AppLocalizations.of(context)!;
        final fallbackDestination = PayoutRoutes.fallbackFromState(
          state,
          defaultDestination: PayoutDestination.methods,
        );

        return NoTransitionPage(
          child: wallet != null
              ? WalletEditPage(
                  onBack: () => _popOrGo(context, fallbackDestination),
                )
              : Center(child: Text(loc.noWalletSelected)),
        );
      },
    ),
    GoRoute(
      name: PayoutRoutes.walletTopUp,
      path: PayoutRoutes.walletTopUpPath,
      pageBuilder: (context, state) {
        final fallbackDestination = PayoutRoutes.fallbackFromState(
          state,
          defaultDestination: PayoutDestination.dashboard,
        );

        return NoTransitionPage(
          child: WalletTopUpPage(
            onBack: () => _popOrGo(context, fallbackDestination),
          ),
        );
      },
    ),
  ],
);

void _startPayment(
  BuildContext context, {
  Recipient? recipient,
  PaymentType? paymentType,
  required PayoutDestination returnTo,
}) {
  context.read<RecipientsProvider>().setCurrentObject(recipient?.id);
  context.pushToPayment(
    paymentType: paymentType,
    returnTo: returnTo,
  );
}

void _openAddRecipient(
  BuildContext context, {
  Recipient? recipient,
}) {
  context.read<RecipientsProvider>().setCurrentObject(recipient?.id);
  context.pushNamed(PayoutRoutes.addRecipient);
}

void _openWalletEdit(
  BuildContext context,
  Wallet wallet, {
  required PayoutDestination returnTo,
}) {
  context.read<WalletsController>().selectWallet(wallet);
  context.pushToEditWallet(returnTo: returnTo);
}

void _openWalletTopUp(
  BuildContext context,
  Wallet wallet, {
  required PayoutDestination returnTo,
}) {
  context.read<WalletsController>().selectWallet(wallet);
  context.pushToWalletTopUp(returnTo: returnTo);
}

void _popOrGo(BuildContext context, PayoutDestination destination) {
  if (Navigator.of(context).canPop()) {
    Navigator.of(context).pop();
  } else {
    context.goToPayout(destination);
  }
}
