import { ChangeDetectionStrategy, Component, computed, inject, input, output, signal } from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { Subject, EMPTY } from 'rxjs';
import { catchError, debounceTime, groupBy, mergeMap, switchMap, tap } from 'rxjs';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CartItemAttribute, CartItemComponent } from '../cart-item/cart-item.component';
import { ModalService } from '../../../core/services/modal.service';
import { CartService } from '../../../core/services/cart/cart.service';
import { ToastService } from '../../../core/services/toast.service';

export interface CartItemMock {
  productVariantId?: number;
  imageUrl: string | null;
  product: string;
  originalPrice: number | null;
  discountedPrice: number;
  discountPercentage: number | null;
  attributes: CartItemAttribute[];
  quantity: number;
}

@Component({
  selector: 'app-cart',
  standalone: true,
  imports: [CartItemComponent],
  templateUrl: './cart.component.html',
  styleUrl: './cart.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class CartComponent {
  private readonly cartService = inject(CartService);
  private readonly modalService = inject(ModalService);
  private readonly toastService = inject(ToastService);
  private readonly quantityUpdates$ = new Subject<{ productVariantId: number; quantity: number }>();

  readonly title = input<string>('CARRITO');
  readonly showClose = input<boolean>(false);
  readonly items = input<CartItemMock[]>([]);
  readonly subtotal = input<number>(0);
  readonly discount = input<number>(0);
  readonly total = input<number>(0);
  readonly backgroundColor = input<string>('#ffffff');

  readonly closed = output<void>();

  protected readonly quantityOverrides = signal<Record<number, number>>({});

  constructor() {
    this.quantityUpdates$.pipe(
      groupBy(update => update.productVariantId),
      mergeMap(group$ => group$.pipe(
        debounceTime(1000),
        switchMap(update => this.cartService.updateItemQuantity(update.productVariantId, update.quantity).pipe(
          tap({
            next: (res) => {
              const msg = res.message || 'Cantidad de producto actualizada.';
              this.toastService.success(msg);
              this.clearOverride(update.productVariantId);
            },
            error: (err: HttpErrorResponse) => {
              console.error('Error updating cart quantity', err);
              const msg = err.error?.message || 'Error al actualizar la cantidad del producto.';
              this.toastService.danger(msg);
              this.clearOverride(update.productVariantId);
            }
          }),
          catchError(() => EMPTY)
        ))
      )),
      takeUntilDestroyed()
    ).subscribe();
  }

  protected getItemQuantity(item: CartItemMock): number {
    if (item.productVariantId !== undefined && this.quantityOverrides()[item.productVariantId] !== undefined) {
      return this.quantityOverrides()[item.productVariantId];
    }
    return item.quantity;
  }

  private clearOverride(productVariantId: number): void {
    this.quantityOverrides.update((overrides) => {
      const copy = { ...overrides };
      delete copy[productVariantId];
      return copy;
    });
  }

  protected onItemQuantityChange(index: number, newQuantity: number): void {
    const mockItem = this.items()[index];
    const productVariantId = mockItem?.productVariantId;
    if (productVariantId) {
      this.quantityOverrides.update((overrides) => ({
        ...overrides,
        [productVariantId]: newQuantity
      }));
      this.quantityUpdates$.next({
        productVariantId,
        quantity: newQuantity
      });
    } else {
      const item = this.cartService.cart()?.items[index];
      if (item) {
        this.quantityOverrides.update((overrides) => ({
          ...overrides,
          [item.product_variant_id]: newQuantity
        }));
        this.quantityUpdates$.next({
          productVariantId: item.product_variant_id,
          quantity: newQuantity
        });
      }
    }
  }

  protected onItemRemove(index: number): void {
    const target = this.resolveRemoveTarget(index);

    if (!target) {
      return;
    }

    this.modalService.openConfirmDelete({
      title: 'Eliminar producto',
      content: `Se eliminara "${target.productName}" del carrito. Esta accion no se puede deshacer.`,
      confirmLabel: 'Eliminar',
      cancelLabel: 'Cancelar'
    }).subscribe((confirmed) => {
      if (confirmed) {
        this.removeItem(target.productVariantId);
      }
    });
  }

  protected readonly formattedSubtotal = computed(() => this.formatCurrency(this.subtotal()));
  protected readonly formattedDiscount = computed(() => this.formatCurrency(this.discount()));
  protected readonly formattedTotal = computed(() => this.formatCurrency(this.total()));

  private formatCurrency(value: number): string {
    const rounded = Math.round(value);
    const parts = rounded.toString().split('.');
    parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '.');
    return `$ ${parts.join(',')}`;
  }

  private resolveRemoveTarget(
    index: number
  ): { productVariantId: number; productName: string } | null {
    const mockItem = this.items()[index];
    const productVariantId = mockItem?.productVariantId;

    if (productVariantId) {
      return {
        productVariantId,
        productName: mockItem.product
      };
    }

    const item = this.cartService.cart()?.items[index];

    if (!item) {
      return null;
    }

    return {
      productVariantId: item.product_variant_id,
      productName: item.product?.nombre ?? 'este producto'
    };
  }

  private removeItem(productVariantId: number): void {
    this.cartService.removeItem(productVariantId).subscribe({
      next: (res) => {
        const msg = res.message || 'Producto eliminado del carrito.';
        this.toastService.info(msg);
      },
      error: (err: HttpErrorResponse) => {
        console.error('Error removing item from cart', err);
        const msg = err.error?.message || 'Error al eliminar el producto del carrito.';
        this.toastService.danger(msg);
      }
    });
  }
}

