import { ProductImageVariantMismatchError } from '../domain/errors.js';
import type { NewProductImage, ProductImage, ProductImageOrderItem } from '../domain/image.js';
import type { ProductImageRepository, ProductRepository } from '../domain/ports.js';

export class ListProductImages {
  constructor(private readonly images: ProductImageRepository) {}

  async execute(productId: string, variantId?: string | null): Promise<ProductImage[]> {
    return this.images.listByProductId(productId, variantId ?? null);
  }
}

export class AttachProductImage {
  constructor(
    private readonly products: ProductRepository,
    private readonly images: ProductImageRepository,
  ) {}

  async execute(productId: string, input: NewProductImage): Promise<ProductImage | undefined> {
    if (!(await this.products.findById(productId))) {
      return undefined;
    }
    if (
      input.variantId !== undefined &&
      input.variantId !== null &&
      !(await this.images.variantBelongsToProduct(productId, input.variantId))
    ) {
      throw new ProductImageVariantMismatchError();
    }
    return this.images.attach(productId, input);
  }
}

export class DetachProductImage {
  constructor(private readonly images: ProductImageRepository) {}

  async execute(productId: string, imageId: string): Promise<boolean> {
    return this.images.detach(productId, imageId);
  }
}

export class ReorderProductImages {
  constructor(private readonly images: ProductImageRepository) {}

  async execute(
    productId: string,
    items: readonly ProductImageOrderItem[],
  ): Promise<ProductImage[]> {
    return this.images.reorder(productId, items);
  }
}
