import { inject } from '@angular/core';
import { CanDeactivateFn, Router } from '@angular/router';
import { TabService } from './tab';
import { logger } from '@isa/core/logging';
import {
  CheckoutMetadataService,
  ShoppingCartService,
} from '@isa/checkout/data-access';
import {
  getNextTabNameHelper,
  formatCustomerTabNameHelper,
  checkCartHasItemsHelper,
} from './helpers';
import { DomainCheckoutService } from '@domain/checkout';
import { CrmTabMetadataService } from '@isa/crm/data-access';
import { firstValueFrom } from 'rxjs';

// TODO: #5484 Move Guard to other location + Use resources for fetching cart data
/**
 * CanDeactivate Guard that manages tab context based on shopping cart state.
 *
 * This guard checks both the regular shopping cart and reward shopping cart:
 * - If BOTH carts are empty (or don't exist), the tab context is cleared and renamed to "Vorgang X"
 * - If EITHER cart still has items:
 *   - Customer context is preserved
 *   - Tab name is updated to show customer name (or organization name for B2B)
 *   - process_type is set to 'cart-checkout' to show cart icon
 *
 * Usage: Apply to checkout-summary routes to automatically manage tab state after order completion.
 */
export const canDeactivateTabCleanup: CanDeactivateFn<unknown> = async () => {
  const tabService = inject(TabService);
  const checkoutMetadataService = inject(CheckoutMetadataService);
  const crmTabMetadataService = inject(CrmTabMetadataService);
  const shoppingCartService = inject(ShoppingCartService);
  const domainCheckoutService = inject(DomainCheckoutService);
  const router = inject(Router);
  const log = logger(() => ({ guard: 'TabCleanup' }));

  const tabId = tabService.activatedTabId();
  if (!tabId) {
    log.warn('No active tab found');
    return true;
  }

  // Check if the target URL contains a tab ID and if it matches the current tab
  // Routes without tab ID (e.g., /filiale/package-inspection, /kunde/dashboard) are global areas
  // Routes with different tab ID (e.g., creating new process) should not affect current tab
  const nextUrl = router.getCurrentNavigation()?.finalUrl?.toString() ?? '';
  const tabIdMatch = nextUrl.match(/\/(\d{10,})\//);
  const targetTabId = tabIdMatch ? parseInt(tabIdMatch[1], 10) : null;

  // Skip cleanup if navigating to global area or different tab
  if (!targetTabId || targetTabId !== tabId) {
    log.debug(
      targetTabId
        ? 'Navigating to different tab, keeping current tab unchanged'
        : 'Navigating to global area (no tab ID), keeping tab unchanged',
      () => ({
        currentTabId: tabId,
        targetTabId,
        nextUrl,
      }),
    );
    return true;
  }

  try {
    // Get shopping cart IDs from tab metadata
    const shoppingCartId = checkoutMetadataService.getShoppingCartId(tabId);
    const rewardShoppingCartId =
      checkoutMetadataService.getRewardShoppingCartId(tabId);

    // Load carts and check if they have items
    let regularCart = null;
    if (shoppingCartId) {
      try {
        regularCart = await shoppingCartService.getShoppingCart(shoppingCartId);
      } catch (error) {
        log.debug('Could not load regular shopping cart', () => ({
          shoppingCartId,
          error: (error as Error).message,
        }));
      }
    }

    let rewardCart = null;
    if (rewardShoppingCartId) {
      try {
        rewardCart =
          await shoppingCartService.getShoppingCart(rewardShoppingCartId);
      } catch (error) {
        log.debug('Could not load reward shopping cart', () => ({
          rewardShoppingCartId,
          error: (error as Error).message,
        }));
      }
    }

    const hasRegularItems = checkCartHasItemsHelper(regularCart);
    const hasRewardItems = checkCartHasItemsHelper(rewardCart);

    log.debug('Cart status check', () => ({
      tabId,
      shoppingCartId,
      rewardShoppingCartId,
      hasRegularItems,
      hasRewardItems,
    }));

    // If either cart has items, preserve context and update tab name with customer info
    if (hasRegularItems || hasRewardItems) {
      log.info(
        'Preserving checkout context - cart(s) still have items',
        () => ({
          tabId,
          hasRegularItems,
          hasRewardItems,
        }),
      );

      try {
        // Get customer from checkout service
        const customer = await firstValueFrom(
          domainCheckoutService.getCustomer({ processId: tabId }),
        );

        if (customer) {
          const name = formatCustomerTabNameHelper(customer);

          if (name) {
            // Update tab name with customer info
            tabService.patchTab(tabId, { name });

            // Ensure process_type is 'cart' for proper cart icon display
            tabService.patchTabMetadata(tabId, {
              process_type: 'cart',
            });

            log.info('Updated tab name with customer info', () => ({
              tabId,
              customerName: name,
            }));
          }
        }
      } catch (error) {
        // If customer data can't be loaded, just log and continue
        log.warn('Could not load customer for tab name update', () => ({
          tabId,
          error: (error as Error).message,
        }));
      }

      return true;
    }

    // Both carts are empty - clean up context
    log.info('Cleaning up checkout context - both carts empty', () => ({
      tabId,
    }));

    // Remove checkout state from store (customer, buyer, payer, etc.)
    domainCheckoutService.removeProcess({ processId: tabId });

    // Clear customer-related metadata (prevents old customer data from being reused)
    crmTabMetadataService.setSelectedCustomerId(tabId, undefined);
    crmTabMetadataService.setSelectedPayerId(tabId, undefined);
    crmTabMetadataService.setSelectedShippingAddressId(tabId, undefined);

    // Create new shopping cart and update Store (this automatically dispatches setShoppingCart action)
    await firstValueFrom(
      domainCheckoutService.createShoppingCart({ processId: tabId }),
    );

    // Clear tab metadata and location history, but keep process_type for cart icon
    tabService.patchTabMetadata(tabId, { process_type: 'cart' });
    tabService.clearLocationHistory(tabId);

    // Rename tab to next "Vorgang X" based on count of existing Vorgang tabs
    const tabName = getNextTabNameHelper(tabService.entityMap());
    tabService.patchTab(tabId, { name: tabName });

    log.info('Tab reset to clean state', () => ({
      tabId,
      name: tabName,
    }));

    return true;
  } catch (error) {
    log.error('Error in checkout cleanup guard', error as Error, () => ({
      tabId,
    }));
    return true; // Allow navigation even if cleanup fails
  }
};
