part of '../product_dtos.dart';

@freezed
class ListProductDto with _$ListProductDto {
  const ListProductDto._();

  const factory ListProductDto({
    @JsonKey(name: "products") required List<ProductDto> products,
    @JsonKey(name: "total_count") required int totalCount,
    @JsonKey(name: "page") required int page,
    @JsonKey(name: "limit") required int limit,
    @JsonKey(name: "total_pages") required int totalPages,
  }) = _ListProductDto;

  factory ListProductDto.fromJson(Map<String, dynamic> json) =>
      _$ListProductDtoFromJson(json);

  ListProduct toDomain() => ListProduct(
    products: products.map((dto) => dto.toDomain()).toList(),
    totalCount: totalCount,
    page: page,
    limit: limit,
    totalPages: totalPages,
  );
}

@freezed
class ProductDto with _$ProductDto {
  const ProductDto._();

  const factory ProductDto({
    @JsonKey(name: "id") String? id,
    @JsonKey(name: "organization_id") String? organizationId,
    @JsonKey(name: "category_id") String? categoryId,
    @JsonKey(name: "sku") String? sku,
    @JsonKey(name: "name") String? name,
    @JsonKey(name: "description") String? description,
    @JsonKey(name: "price") double? price,
    @JsonKey(name: "cost") double? cost,
    @JsonKey(name: "business_type") String? businessType,
    @JsonKey(name: "image_url") String? imageUrl,
    @JsonKey(name: "printer_type") String? printerType,
    @JsonKey(name: "print_to_checker") bool? printToChecker,
    @JsonKey(name: "metadata") Map<String, dynamic>? metadata,
    @JsonKey(name: "is_active") bool? isActive,
    @JsonKey(name: "created_at") String? createdAt,
    @JsonKey(name: "updated_at") String? updatedAt,
    @JsonKey(name: "variants") List<ProductVariantDto>? variants,
  }) = _ProductDto;

  factory ProductDto.fromJson(Map<String, dynamic> json) =>
      _$ProductDtoFromJson(json);

  /// Mapping ke domain
  Product toDomain() => Product(
    id: id ?? '',
    organizationId: organizationId ?? '',
    categoryId: categoryId ?? '',
    sku: sku ?? '',
    name: name ?? '',
    description: description ?? '',
    price: price ?? 0.0,
    cost: cost ?? 0.0,
    businessType: businessType ?? '',
    imageUrl: imageUrl ?? '',
    printerType: printerType ?? '',
    printToChecker: printToChecker ?? false,
    metadata: metadata ?? {},
    isActive: isActive ?? false,
    createdAt: createdAt ?? '',
    updatedAt: updatedAt ?? '',
    variants: variants?.map((v) => v.toDomain()).toList() ?? [],
  );

  Map<String, dynamic> toMap() => {
    'id': id,
    'organization_id': organizationId,
    'category_id': categoryId,
    'sku': sku,
    'name': name,
    'description': description,
    'price': price,
    'cost': cost,
    'business_type': businessType,
    'image_url': imageUrl,
    'printer_type': printerType,
    'print_to_checker': printToChecker == true ? 1 : 0,
    'metadata': metadata != null ? jsonEncode(metadata) : null,
    'is_active': isActive == true ? 1 : 0,
    'created_at': createdAt,
    'updated_at': updatedAt,
  };

  factory ProductDto.fromMap(
    Map<String, dynamic> map,
    List<ProductVariantDto> variants,
  ) => ProductDto(
    id: map['id'] as String?,
    organizationId: map['organization_id'] as String?,
    categoryId: map['category_id'] as String?,
    sku: map['sku'] as String?,
    name: map['name'] as String?,
    description: map['description'] as String?,
    price: map['price'] != null ? (map['price'] as num).toDouble() : null,
    cost: map['cost'] != null ? (map['cost'] as num).toDouble() : null,
    businessType: map['business_type'] as String?,
    imageUrl: map['image_url'] as String?,
    printerType: map['printer_type'] as String?,
    printToChecker: map['print_to_checker'] != null
        ? (map['print_to_checker'] as int) == 1
        : null,
    metadata: map['metadata'] != null
        ? jsonDecode(map['metadata'] as String) as Map<String, dynamic>
        : null,
    isActive: map['is_active'] != null ? (map['is_active'] as int) == 1 : null,

    createdAt: map['created_at'] as String?,
    updatedAt: map['updated_at'] as String?,
    variants: variants,
  );

  factory ProductDto.fromDomain(Product product) => ProductDto(
    id: product.id,
    organizationId: product.organizationId,
    categoryId: product.categoryId,
    sku: product.sku,
    name: product.name,
    description: product.description,
    price: product.price,
    cost: product.cost,
    businessType: product.businessType,
    imageUrl: product.imageUrl,
    printerType: product.printerType,
    printToChecker: product.printToChecker,
    metadata: product.metadata,
    isActive: product.isActive,
    createdAt: product.createdAt,
    updatedAt: product.updatedAt,
    variants: product.variants
        .map((v) => ProductVariantDto.fromDomain(v))
        .toList(),
  );
}

@freezed
class ProductVariantDto with _$ProductVariantDto {
  const ProductVariantDto._();

  const factory ProductVariantDto({
    @JsonKey(name: "id") String? id,
    @JsonKey(name: "product_id") String? productId,
    @JsonKey(name: "name") String? name,
    @JsonKey(name: "price_modifier") double? priceModifier,
    @JsonKey(name: "cost") double? cost,
    @JsonKey(name: "metadata") Map<String, dynamic>? metadata,
    @JsonKey(name: "created_at") String? createdAt,
    @JsonKey(name: "updated_at") String? updatedAt,
  }) = _ProductVariantDto;

  factory ProductVariantDto.fromJson(Map<String, dynamic> json) =>
      _$ProductVariantDtoFromJson(json);

  /// Mapping ke domain
  ProductVariant toDomain() => ProductVariant(
    id: id ?? '',
    productId: productId ?? '',
    name: name ?? '',
    priceModifier: priceModifier ?? 0.0,
    cost: cost ?? 0.0,
    metadata: metadata ?? {},
    createdAt: createdAt ?? '',
    updatedAt: updatedAt ?? '',
  );

  Map<String, dynamic> toMap() => {
    'id': id,
    'product_id': productId,
    'name': name,
    'price_modifier': priceModifier,
    'cost': cost,
    'metadata': metadata != null ? jsonEncode(metadata) : null,
    'created_at': createdAt,
    'updated_at': updatedAt,
  };

  factory ProductVariantDto.fromMap(Map<String, dynamic> map) =>
      ProductVariantDto(
        id: map['id'] as String?,
        productId: map['product_id'] as String?,
        name: map['name'] as String?,
        priceModifier: map['price_modifier'] != null
            ? (map['price_modifier'] as num).toDouble()
            : null,
        cost: map['cost'] != null ? (map['cost'] as num).toDouble() : null,
        metadata: map['metadata'] != null
            ? jsonDecode(map['metadata'] as String) as Map<String, dynamic>
            : null,
        createdAt: map['created_at'] as String?,
        updatedAt: map['updated_at'] as String?,
      );

  factory ProductVariantDto.fromDomain(ProductVariant variant) =>
      ProductVariantDto(
        id: variant.id,
        productId: variant.productId,
        name: variant.name,
        priceModifier: variant.priceModifier,
        cost: variant.cost,
        metadata: variant.metadata,
        createdAt: variant.createdAt,
        updatedAt: variant.updatedAt,
      );
}
