import { HttpErrorResponse } from '@angular/common/http';
import { Component, computed, DestroyRef, inject, OnInit, signal } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import {
  ActivatedRoute,
  NavigationEnd,
  PRIMARY_OUTLET,
  Router,
  RouterOutlet,
} from '@angular/router';
import { filter } from 'rxjs';
import { TenantService } from '../../services/tenant.service';
import { CartService } from '../../services/cart/cart.service';
import { StoreFooterComponent, StoreFooterSection } from './store-footer/store-footer.component';
import { StoreHeaderComponent } from './store-header/store-header.component';
import { CartComponent, CartItemMock } from '../../../shared/components/cart/cart.component';
import { ButtonComponent } from '../../../shared/components/button/button.component';
import { CartItem, CartItemVariantValue } from '../../services/cart/cart.interface';
import { AuthService } from '../../services/auth/auth.service';
import { findMenu } from '../../services/menu.utils';
import {
  CheckoutService,
  isExpiredStockReservationResponse,
} from '../../services/checkout.service';
import { ToastService } from '../../services/toast.service';
import { Category } from '../../services/tenant.interface';
import { CheckoutCountdownService } from '../../services/checkout-countdown.service';

@Component({
  selector: 'app-store-layout',
  imports: [
    RouterOutlet,
    StoreHeaderComponent,
    StoreFooterComponent,
    CartComponent,
    ButtonComponent,
  ],
  templateUrl: './store-layout.component.html',
  styleUrl: './store-layout.component.scss',
})
export class StoreLayoutComponent implements OnInit {
  private readonly tenantService = inject(TenantService);
  private readonly cartService = inject(CartService);
  private readonly authService = inject(AuthService);
  private readonly checkoutService = inject(CheckoutService);
  private readonly checkoutCountdownService = inject(CheckoutCountdownService);
  private readonly toastService = inject(ToastService);
  private readonly router = inject(Router);
  private readonly route = inject(ActivatedRoute);
  private readonly destroyRef = inject(DestroyRef);

  protected readonly isCartOpen = signal(false);
  protected readonly isCheckoutRoute = signal(this.isCheckoutUrl(this.router.url));
  protected readonly checkoutRemainingSeconds = this.checkoutCountdownService.remainingSeconds;
  protected readonly isCreatingPurchase = signal(false);
  protected readonly displayCart = computed(() => this.tenant()?.display_cart ?? true);
  protected readonly cartEditingPolicy = computed(() => this.tenant()?.cart_editing_policy ?? null);
  protected readonly canModifyCart = computed(
    () => this.cartEditingPolicy()?.allow_modify ?? false,
  );
  protected readonly canDeleteCartItems = computed(
    () => this.cartEditingPolicy()?.allow_delete ?? false,
  );
  protected readonly canUpdateCartQuantity = computed(
    () => this.cartEditingPolicy()?.allow_update_quantity ?? false,
  );
  protected readonly canUpdateCartVariant = computed(
    () => this.cartEditingPolicy()?.allow_update_variant ?? false,
  );

  protected readonly cartSubtotal = computed(() => {
    const cart = this.cartService.cart();
    return cart ? parseFloat(cart.subtotal) : 0;
  });

  protected readonly cartDiscount = computed(() => 0);

  protected readonly cartTotal = computed(() => this.cartSubtotal() - this.cartDiscount());

  protected readonly mappedCartItems = computed<CartItemMock[]>(() => {
    const cart = this.cartService.cart();
    if (!cart || !cart.items) return [];
    return cart.items.map((item) => this.mapCartItemToMock(item));
  });

  private mapCartItemToMock(item: CartItem): CartItemMock {
    const fullName = item.nombre ?? '';
    let product = fullName;
    let attributes: { label: string; value: string }[] = [];

    const match = fullName.match(/^(.*?)\s*\((.*?)\)$/);
    if (match) {
      product = match[1];
      const attributesString = match[2];
      attributes = attributesString.split(',').map((attr) => {
        const parts = attr.split(':');
        if (parts.length === 2) {
          return { label: parts[0].trim(), value: parts[1].trim() };
        }
        return { label: '', value: attr.trim() };
      });
    }

    const selectedVariant = item.variant;

    if (selectedVariant) {
      attributes = Object.entries(selectedVariant.values).map(([label, value]) => ({
        label: this.formatAttributeLabel(label),
        value: this.formatAttributeValue(value),
      }));
    }

    return {
      cartItemId: item.id,
      imageUrl: item.imagen,
      product,
      originalPrice: null,
      discountedPrice: parseFloat(item.precio_unitario),
      discountPercentage: null,
      attributes,
      quantity: item.cantidad,
      variantId: item.variant_id,
      variants: item.variants,
    };
  }

  private formatAttributeLabel(value: string): string {
    const label = value.replace(/[_-]+/g, ' ');
    return label.charAt(0).toUpperCase() + label.slice(1);
  }

  private formatAttributeValue(value: CartItemVariantValue): string {
    const values = Array.isArray(value) ? value : [value];
    return values.map((item) => (typeof item === 'string' ? item : item.label)).join(', ');
  }

  protected readonly currentYear = new Date().getFullYear();
  protected readonly tenant = this.tenantService.tenant;
  protected readonly user = this.authService.user;
  protected readonly isAuthenticated = this.authService.isAuthenticated;
  protected readonly ticketsMenu = computed(() =>
    findMenu(this.tenant()?.menues ?? [], 'account.tickets'),
  );
  protected readonly accountNavigationMenus = computed(() => {
    const accountMenu = findMenu(this.tenant()?.menues ?? [], 'account');

    if (!accountMenu) {
      return [];
    }

    const profile = accountMenu.submenues.find((menu) => menu.code === 'account.profile');
    const purchases = accountMenu.submenues.find((menu) => menu.code === 'account.purchases');

    return [
      ...(profile ? [{ ...accountMenu, route: profile.route }] : []),
      ...(purchases ? [purchases] : []),
    ];
  });

  protected readonly cartQuantity = computed(() => {
    const cart = this.cartService.cart();
    if (!cart || !cart.items) return 0;
    return cart.items.reduce((total, item) => total + item.cantidad, 0);
  });

  ngOnInit(): void {
    this.router.events
      .pipe(
        filter((event): event is NavigationEnd => event instanceof NavigationEnd),
        takeUntilDestroyed(this.destroyRef),
      )
      .subscribe((event) => {
        const isCheckoutRoute = this.isCheckoutUrl(event.urlAfterRedirects);
        this.isCheckoutRoute.set(isCheckoutRoute);

        if (isCheckoutRoute) {
          this.isCartOpen.set(false);
        }
      });

    this.route.queryParamMap.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => {
      if (params.get('openCart') === 'true' && !this.isCheckoutRoute()) {
        this.isCartOpen.set(true);
      }
    });

    this.cartService.loadCart().subscribe({
      error: (err) => console.error('Error loading cart', err),
    });
  }

  private isCheckoutUrl(url: string): boolean {
    const primarySegments = this.router.parseUrl(url).root.children[PRIMARY_OUTLET]?.segments ?? [];

    return primarySegments[0]?.path === 'checkout';
  }

  protected onLoginClick(): void {
    void this.router.navigate(['/login']);
  }

  protected onCartClick(): void {
    if (this.isCheckoutRoute()) {
      return;
    }

    this.isCartOpen.update((isOpen) => !isOpen);
  }

  protected onSearch(term: string): void {
    void this.router.navigate(['/buscar'], {
      queryParams: { q: term, page: 1 },
    });
  }

  protected onCategorySelect(category: Category): void {
    void this.router.navigate(['/categoria', category.id], {
      queryParams: { page: 1 },
    });
  }

  protected onTicketsClick(): void {
    const route = this.ticketsMenu()?.route;

    if (route) {
      void this.router.navigate([route]);
    }
  }

  protected async onLogoutClick(): Promise<void> {
    const isLeavingCheckout = this.router.url.startsWith('/checkout');

    // Leave checkout before closing the authenticated session so its component
    // can stop payment polling cleanly. The checkout itself remains pending.
    if (isLeavingCheckout) {
      const navigationSucceeded = await this.router.navigate(['/']);

      if (!navigationSucceeded) {
        return;
      }
    }

    this.authService.logout().subscribe({
      next: () => {
        this.cartService.clearCart();
        this.isCartOpen.set(false);

        if (!isLeavingCheckout) {
          void this.router.navigate(['/']);
        }
      },
      error: (err) => console.error('Error logging out', err),
    });
  }

  protected async onCheckoutClick(): Promise<void> {
    if (this.isCreatingPurchase()) {
      return;
    }

    const cart = this.cartService.cart();
    const tenant = this.tenantService.tenant();
    const user = this.authService.user();

    if (!user) {
      this.isCartOpen.set(false);
      void this.router.navigate(['/login'], { queryParams: { returnUrl: '/' } });
      return;
    }

    if (!cart?.id || !tenant) {
      this.toastService.danger('No hay un carrito activo para iniciar la compra.');
      return;
    }

    this.isCreatingPurchase.set(true);
    try {
      const purchase = await this.checkoutService.startCheckout(tenant.codigo, {
        cart_id: cart.id,
      });

      this.isCartOpen.set(false);
      await this.router.navigate(['/checkout', purchase.id]);
    } catch (error) {
      console.error('Failed to create cart purchase:', error);
      const message =
        error instanceof HttpErrorResponse && typeof error.error?.message === 'string'
          ? error.error.message
          : 'No se pudo iniciar la compra.';
      this.toastService.danger(message);

      if (error instanceof HttpErrorResponse && isExpiredStockReservationResponse(error.error)) {
        this.cartService.loadCart(true).subscribe({
          error: (refreshError) => console.error('Error refreshing expired cart', refreshError),
        });
      }
    } finally {
      this.isCreatingPurchase.set(false);
    }
  }

  protected readonly footerSections = computed<StoreFooterSection[]>(() => {
    const helpSubmenues = findMenu(this.tenant()?.menues ?? [], 'help')?.submenues ?? [];

    return [
      {
        heading: 'Cuenta',
        links: [
          ...this.accountNavigationMenus().map((menu) => ({
            label: menu.label,
            routerLink: menu.route,
          })),
          { label: 'Cerrar sesion', action: 'logout' },
        ],
      },
      {
        heading: 'Ayuda',
        links: helpSubmenues.map((menu) => ({
          label: menu.label,
          routerLink: menu.route,
        })),
      },
    ];
  });
}
