import 'package:json_annotation/json_annotation.dart';
import 'package:niogu_ecommerce_v1/core/enums/review_display_policy.dart';
import 'package:niogu_ecommerce_v1/core/enums/review_display_type.dart';
import 'package:niogu_ecommerce_v1/core/enums/stock_type.dart';
import 'package:niogu_ecommerce_v1/core/utils/converter.dart';
import 'package:niogu_ecommerce_v1/features/product/domain/entities/product.dart';

part 'product_response_model.g.dart';

@JsonSerializable()
class ProductDetailResponse {
  @JsonKey(name: 'review_display_type')
  final String reviewDisplayType;

  @JsonKey(name: 'review_display_policy')
  final String reviewDisplayPolicy;

  @JsonKey(name: 'product_info')
  final ProductInfoResponse productInfo;

  const ProductDetailResponse({
    required this.reviewDisplayType,
    required this.reviewDisplayPolicy,
    required this.productInfo,
  });

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

  Map<String, dynamic> toJson() => _$ProductDetailResponseToJson(this);

  ProductDetail toProductDetail() {
    return ProductDetail(
      reviewDisplayType: ReviewDisplayType.values.byName(reviewDisplayType),
      reviewDisplayPolicy: ReviewDisplayPolicy.values.byName(reviewDisplayPolicy),
      productInfo: productInfo.toProductInfo(),
    );
  }
}

@JsonSerializable()
class ProductInfoResponse {
  final String id;

  @JsonKey(name: 'server_image_url')
  final List<String> serverImageUrls;

  final String name;

  @JsonKey(name: 'has_variant')
  final bool hasVariant;

  final String unit;

  @JsonKey(name: 'variants')
  final List<ProductVariantResponse> variants;

  final String? description;

  const ProductInfoResponse({
    required this.id,
    required this.serverImageUrls,
    required this.name,
    required this.hasVariant,
    required this.unit,
    required this.variants,
    required this.description,
  });

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

  Map<String, dynamic> toJson() =>  _$ProductInfoResponseToJson(this); 

  ProductInfo toProductInfo() {
    return ProductInfo(
      id: id,
      images: serverImageUrls,
      name: name,
      hasVariant: hasVariant,
      unit: unit,
      variants: variants.map((v) => v.toProductVariant()).toList(),
      description: description,
    );
  }
}

@JsonSerializable()
class ProductVariantResponse {
  final String id;

  @JsonKey(name: 'server_image_url')
  final String? serverImageUrl;

  final String name;

  @JsonKey(name: 'is_product_variant')
  final bool isProductVariant;

  @JsonKey(name: 'selling_price')
  final double sellingPrice;

  @JsonKey(name: 'stock_type')
  final String stockType;

  @JsonKey(fromJson: toDouble)
  final double stock;

  @JsonKey(name: 'total_sold', fromJson: toDouble)
  final double totalSold;

  @JsonKey(name: 'reviews')
  final List<ProductReviewResponse> reviews;

  const ProductVariantResponse({
    required this.id,
    required this.serverImageUrl,
    required this.name,
    required this.isProductVariant,
    required this.sellingPrice,
    required this.stockType,
    required this.stock,
    required this.totalSold,
    required this.reviews,
  });

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

  Map<String, dynamic> toJson() =>  _$ProductVariantResponseToJson(this); 

  ProductVariant toProductVariant() {
    return ProductVariant(
      id: id,
      image: serverImageUrl,
      name: name,
      isProductVariant: isProductVariant,
      sellingPrice: sellingPrice,
      stockType: StockType.values.byName(stockType),
      stock: stock,
      totalSold: totalSold,
      reviews: reviews.map((r) => r.toProductReview()).toList(),
    );
  }
}

@JsonSerializable()
class ProductReviewResponse {
  final String id;

  @JsonKey(name: 'customer_name')
  final String customerName;

  @JsonKey(name: 'rating_count')
  final int ratingCount;

  final String? comment;

  const ProductReviewResponse({
    required this.id,
    required this.customerName,
    required this.ratingCount,
    required this.comment,
  });

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

  Map<String, dynamic> toJson() =>  _$ProductReviewResponseToJson(this); 

  ProductReview toProductReview() {
    return ProductReview(
      id: id,
      customerName: customerName,
      ratingCount: ratingCount,
      comment: comment,
    );
  }
}
