import {
  ChangeDetectionStrategy,
  Component,
  computed,
  effect,
  input,
  model,
  output,
} from '@angular/core';
import { ButtonComponent } from '../button/button.component';
import { QuantitySelectorComponent } from '../quantity-selector/quantity-selector.component';
import { TooltipComponent } from '../tooltip/tooltip.component';
import {
  VariantSelectorComponent,
  VariantSelectorVariant,
} from '../variant-selector/variant-selector.component';

export interface Variant extends VariantSelectorVariant {
  label?: string;
  descripcion?: string | null;
  precio?: string | number;
  maximum_addable_quantity?: number | null;
  unavailable_message?: string | null;
}

@Component({
  selector: 'app-product-row-card',
  standalone: true,
  imports: [ButtonComponent, QuantitySelectorComponent, TooltipComponent, VariantSelectorComponent],
  templateUrl: './product-row-card.component.html',
  styleUrl: './product-row-card.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ProductRowCardComponent {
  // Configurable inputs
  readonly title = input<string>('');
  readonly description = input<string>('');
  readonly price = input<number>(0);
  readonly maximumAddableQuantity = input<number | null>(null);
  readonly unavailableMessage = input<string | null>(null);
  readonly variants = input<Variant[]>([]);
  readonly saving = input(false);

  // Internal state models
  readonly quantity = model<number>(1);
  readonly selectedVariant = model<unknown>(null);

  // Interactive events
  readonly buy = output<{ quantity: number; variant: unknown }>();
  readonly addToCart = output<{ quantity: number; variant: unknown }>();

  protected readonly selectedVariantData = computed(() =>
    this.variants().find((variant) => Object.is(variant.id, this.selectedVariant())),
  );
  protected readonly effectiveDescription = computed(
    () => this.selectedVariantData()?.descripcion ?? this.description(),
  );
  protected readonly effectivePrice = computed(() => {
    const variantPrice = Number(this.selectedVariantData()?.precio);

    return Number.isFinite(variantPrice) ? variantPrice : this.price();
  });
  protected readonly effectiveMaximum = computed(
    () => this.selectedVariantData()?.maximum_addable_quantity ?? this.maximumAddableQuantity(),
  );
  protected readonly unavailable = computed(() => this.effectiveMaximum() === 0);
  protected readonly effectiveUnavailableMessage = computed(() => {
    const selectedVariant = this.selectedVariantData();

    return selectedVariant
      ? (selectedVariant.unavailable_message ?? null)
      : this.unavailableMessage();
  });

  readonly formattedPrice = computed(() => this.formatCurrency(this.effectivePrice()));

  constructor() {
    effect(() => {
      const maximum = this.effectiveMaximum();

      if (maximum !== null && maximum > 0 && this.quantity() > maximum) {
        this.quantity.set(maximum);
      }
    });
  }

  protected onAddToCart(): void {
    if (this.saving() || this.unavailable()) {
      return;
    }

    this.addToCart.emit({
      quantity: this.quantity(),
      variant: this.selectedVariant(),
    });
  }

  protected onBuy(): void {
    if (this.unavailable()) return;

    this.buy.emit({
      quantity: this.quantity(),
      variant: this.selectedVariant(),
    });
  }

  /**
   * Helper method to format currency numbers to Argentine Pesos style "$ XX.XXX".
   */
  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(',')}`;
  }
}
