import 'package:flutter/widgets.dart';

import 'package:collection/collection.dart';

import 'package:go_router/go_router.dart';

import 'package:pshared/models/payment/type.dart';

import 'package:pweb/widgets/sidebar/destinations.dart';


class PayoutRoutes {
  static const dashboard = 'dashboard';
  static const sendPayout = payment;
  static const recipients = 'payout-recipients';
  static const invitations = 'payout-invitations';
  static const addRecipient = 'payout-add-recipient';
  static const editRecipient = 'payout-edit-recipient';
  static const payment = 'payout-payment';
  static const settings = 'payout-settings';
  static const reports = 'payout-reports';
  static const reportPayment = 'payout-report-payment';
  static const methods = 'payout-methods';
  static const editWallet = 'payout-edit-wallet';
  static const walletTopUp = 'payout-wallet-top-up';

  static const paymentTypeQuery = 'paymentType';
  static const destinationLedgerAccountRefQuery = 'destinationLedgerAccountRef';
  static const reportPaymentIdQuery = 'paymentId';

  static const dashboardPath = '/dashboard';
  static const recipientsPath = '/recipients';
  static const invitationsPath = '/invitations';
  static const addRecipientPath = '/recipients/add';
  static const editRecipientPath = '/recipients/edit';
  static const paymentPath = '/payment';
  static const settingsPath = '/settings';
  static const reportsPath = '/reports';
  static const reportPaymentPath = '/reports/payment';
  static const methodsPath = '/methods';
  static const editWalletPath = '/methods/edit';
  static const walletTopUpPath = '/wallet/top-up';

  static String nameFor(PayoutDestination destination) {
    switch (destination) {
      case PayoutDestination.dashboard:
        return dashboard;
      case PayoutDestination.sendPayout:
      return payment;
    case PayoutDestination.recipients:
      return recipients;
    case PayoutDestination.invitations:
      return invitations;
    case PayoutDestination.addrecipient:
      return addRecipient;
    case PayoutDestination.payment:
      return payment;
    case PayoutDestination.settings:
        return settings;
      case PayoutDestination.reports:
        return reports;
      case PayoutDestination.methods:
        return methods;
      case PayoutDestination.editwallet:
        return editWallet;
      case PayoutDestination.walletTopUp:
        return walletTopUp;
    }
  }

  static String pathFor(PayoutDestination destination) {
    switch (destination) {
      case PayoutDestination.dashboard:
        return dashboardPath;
      case PayoutDestination.sendPayout:
      return paymentPath;
    case PayoutDestination.recipients:
      return recipientsPath;
    case PayoutDestination.invitations:
      return invitationsPath;
    case PayoutDestination.addrecipient:
      return addRecipientPath;
    case PayoutDestination.payment:
      return paymentPath;
    case PayoutDestination.settings:
        return settingsPath;
      case PayoutDestination.reports:
        return reportsPath;
      case PayoutDestination.methods:
        return methodsPath;
      case PayoutDestination.editwallet:
        return editWalletPath;
      case PayoutDestination.walletTopUp:
        return walletTopUpPath;
    }
  }

  static PayoutDestination? destinationFor(String? routeName) {
    switch (routeName) {
      case dashboard:
        return PayoutDestination.dashboard;
      case sendPayout:
      return PayoutDestination.payment;
    case recipients:
      return PayoutDestination.recipients;
    case invitations:
      return PayoutDestination.invitations;
    case addRecipient:
      return PayoutDestination.addrecipient;
      case editRecipient:
        return PayoutDestination.addrecipient;
    case settings:
      return PayoutDestination.settings;
      case reports:
        return PayoutDestination.reports;
      case methods:
        return PayoutDestination.methods;
      case editWallet:
        return PayoutDestination.editwallet;
      case walletTopUp:
        return PayoutDestination.walletTopUp;
      default:
        return null;
    }
  }

  static Map<String, String> buildQueryParameters({
    PaymentType? paymentType,
    String? destinationLedgerAccountRef,
  }) {
    final params = <String, String>{
      if (paymentType != null) paymentTypeQuery: paymentType.name,
      if (destinationLedgerAccountRef != null &&
          destinationLedgerAccountRef.trim().isNotEmpty)
        destinationLedgerAccountRefQuery: destinationLedgerAccountRef.trim(),
    };
    return params;
  }

  static PaymentType? paymentTypeFromState(GoRouterState state) =>
      paymentTypeFromRaw(state.uri.queryParameters[paymentTypeQuery]);

  static PaymentType? paymentTypeFromRaw(String? raw) => raw == null
      ? null
      : PaymentType.values.firstWhereOrNull((type) => type.name == raw);

  static String? destinationLedgerAccountRefFromState(GoRouterState state) =>
      destinationLedgerAccountRefFromRaw(
        state.uri.queryParameters[destinationLedgerAccountRefQuery],
      );

  static String? destinationLedgerAccountRefFromRaw(String? raw) {
    final value = raw?.trim();
    if (value == null || value.isEmpty) return null;
    return value;
  }
}

extension PayoutNavigation on BuildContext {
  void goToPayout(PayoutDestination destination) =>
      goNamed(PayoutRoutes.nameFor(destination));

  void pushToPayout(PayoutDestination destination) =>
      pushNamed(PayoutRoutes.nameFor(destination));

  void goToPayment({
    PaymentType? paymentType,
    String? destinationLedgerAccountRef,
  }) => goNamed(
        PayoutRoutes.payment,
        queryParameters: PayoutRoutes.buildQueryParameters(
          paymentType: paymentType,
      destinationLedgerAccountRef: destinationLedgerAccountRef,
        ),
      );

  void goToReportPayment(String paymentId) => goNamed(
    PayoutRoutes.reportPayment,
    queryParameters: {PayoutRoutes.reportPaymentIdQuery: paymentId},
  );

  void pushToReportPayment(String paymentId) => pushNamed(
    PayoutRoutes.reportPayment,
    queryParameters: {PayoutRoutes.reportPaymentIdQuery: paymentId},
  );

  void pushToWalletTopUp() => pushNamed(PayoutRoutes.walletTopUp);

  void pushToEditWallet() => pushNamed(PayoutRoutes.editWallet);
}
