import { Money } from '../value-objects/Money';
import { Result, success, failure } from '../value-objects/Result';
import { ValidationError } from '../errors/DomainError';

export interface ProductProps {
  id: string;
  name: string;
  description: string;
  price: Money;
  stock: number;
  createdAt: Date;
  updatedAt: Date;
}

export class Product {
  private constructor(private props: ProductProps) {}

  static create(props: Omit<ProductProps, 'createdAt' | 'updatedAt'> & {
    createdAt?: Date;
    updatedAt?: Date;
  }): Result<Product, ValidationError> {
    if (!props.id || props.id.trim().length === 0) {
      return failure(new ValidationError('Product ID is required'));
    }
    if (!props.name || props.name.trim().length < 3) {
      return failure(new ValidationError('Name must be at least 3 characters'));
    }
    if (props.stock < 0) {
      return failure(new ValidationError('Stock cannot be negative'));
    }

    const now = new Date();
    return success(
      new Product({
        ...props,
        createdAt: props.createdAt ?? now,
        updatedAt: props.updatedAt ?? now,
      })
    );
  }

  getId(): string {
    return this.props.id;
  }

  getName(): string {
    return this.props.name;
  }

  getPrice(): Money {
    return this.props.price;
  }

  getStock(): number {
    return this.props.stock;
  }

  isInStock(): boolean {
    return this.props.stock > 0;
  }

  decreaseStock(quantity: number): Result<void, ValidationError> {
    if (quantity <= 0) {
      return failure(new ValidationError('Quantity must be positive'));
    }
    if (this.props.stock < quantity) {
      return failure(new ValidationError('Insufficient stock'));
    }
    this.props.stock -= quantity;
    this.props.updatedAt = new Date();
    return success(undefined);
  }

  toJSON() {
    return {
      id: this.props.id,
      name: this.props.name,
      description: this.props.description,
      price: {
        amount: this.props.price.getAmount(),
        currency: this.props.price.getCurrency(),
      },
      stock: this.props.stock,
      createdAt: this.props.createdAt,
      updatedAt: this.props.updatedAt,
    };
  }
}
