import { api } from '@/lib/api';
import { ApiProduct, ProductDetailData, convertApiProductToDetailData, SelectedVariant, ApiProductVariant } from '@/types/api';

export class ProductDetailService {
  /**
   * Fetch a single product by slug with all variants
   */
  static async getProductBySlug(slug: string): Promise<ProductDetailData> {
    try {
      console.log('Fetching product with slug:', slug);
      const response = await api.get<{ data: ApiProduct } | ApiProduct>(`/products/${slug}`);
      console.log('Raw API Response:', response);
      
      // Handle both wrapped and unwrapped responses
      let productData: ApiProduct;
      if ('data' in response && response.data) {
        // Response is wrapped in a data property
        productData = response.data;
        console.log('Using wrapped data:', productData);
      } else {
        // Response is direct product data
        productData = response as ApiProduct;
        console.log('Using direct data:', productData);
      }
      
      // Add validation for required fields
      if (!productData) {
        throw new Error('No product data received from API');
      }
      
      if (!productData.id) {
        console.error('Invalid product data - missing ID:', productData);
        throw new Error('Invalid product data received');
      }
      
      const convertedData = convertApiProductToDetailData(productData);
      console.log('Converted product data:', convertedData);
      
      return convertedData;
    } catch (error) {
      console.error('Error in getProductBySlug:', error);
      if (error instanceof Error) {
        console.error('Error details:', {
          message: error.message,
          stack: error.stack,
        });
        throw new Error(`Failed to fetch product details: ${error.message}`);
      }
      throw new Error('Failed to fetch product details: Unknown error');
    }
  }

  /**
   * Find a specific variant based on selected size and color
   */
  static findVariant(
    variants: ApiProductVariant[], 
    selectedSize?: string, 
    selectedColor?: string
  ): ApiProductVariant | undefined {
    if (!variants.length) return undefined;

    // If no size or color selected, return first available variant
    if (!selectedSize && !selectedColor) {
      return variants[0];
    }

    // Find exact match first
    const exactMatch = variants.find(variant => 
      (!selectedSize || variant.size === selectedSize) &&
      (!selectedColor || variant.color === selectedColor)
    );

    if (exactMatch) return exactMatch;

    // If no exact match, find partial match
    if (selectedSize) {
      const sizeMatch = variants.find(variant => variant.size === selectedSize);
      if (sizeMatch) return sizeMatch;
    }

    if (selectedColor) {
      const colorMatch = variants.find(variant => variant.color === selectedColor);
      if (colorMatch) return colorMatch;
    }

    // Return first variant as fallback
    return variants[0];
  }

  /**
   * Get selected variant information with computed properties
   */
  static getSelectedVariant(
    product: ProductDetailData,
    selectedSize?: string,
    selectedColor?: string
  ): SelectedVariant {
    const variant = this.findVariant(product.variants, selectedSize, selectedColor);
    
    return {
      size: selectedSize,
      color: selectedColor,
      variant,
      price: variant ? parseFloat(variant.price.toString()) : product.base_price,
      stock: variant ? variant.stock : 0
    };
  }

  /**
   * Get available colors for a selected size
   */
  static getAvailableColorsForSize(variants: ApiProductVariant[], size: string): string[] {
    return [...new Set(
      variants
        .filter(variant => variant.size === size && variant.stock > 0)
        .map(variant => variant.color)
        .filter(Boolean)
    )];
  }

  /**
   * Get available sizes for a selected color
   */
  static getAvailableSizesForColor(variants: ApiProductVariant[], color: string): string[] {
    return [...new Set(
      variants
        .filter(variant => variant.color === color && variant.stock > 0)
        .map(variant => variant.size)
        .filter(Boolean)
    )];
  }

  /**
   * Check if a specific variant combination is available
   */
  static isVariantAvailable(
    variants: ApiProductVariant[],
    size?: string,
    color?: string
  ): boolean {
    const variant = this.findVariant(variants, size, color);
    return variant ? variant.stock > 0 : false;
  }

  /**
   * Get variant by ID
   */
  static getVariantById(variants: ApiProductVariant[], variantId: number): ApiProductVariant | undefined {
    return variants.find(variant => variant.id === variantId);
  }

  /**
   * Format price for display
   */
  static formatPrice(price: number | string): string {
    const numPrice = typeof price === 'string' ? parseFloat(price) : price;
    return `$${numPrice.toFixed(2)}`;
  }

  /**
   * Calculate discount percentage if there's a price difference
   */
  static calculateDiscount(originalPrice: number, salePrice: number): number {
    if (originalPrice <= salePrice) return 0;
    return Math.round(((originalPrice - salePrice) / originalPrice) * 100);
  }

  /**
   * Get stock status text
   */
  static getStockStatus(stock: number): { status: string; color: string } {
    if (stock === 0) {
      return { status: 'Out of Stock', color: 'text-red-600' };
    } else if (stock < 5) {
      return { status: `Only ${stock} left`, color: 'text-orange-600' };
    } else if (stock < 10) {
      return { status: 'Low Stock', color: 'text-yellow-600' };
    } else {
      return { status: 'In Stock', color: 'text-green-600' };
    }
  }
}