"""
Canvas Image API - Hierarchical Image Fallback System

This module provides intelligent image serving with fallback logic:
1. Product-specific images
2. Subtype-level fallbacks
3. Type-level fallbacks
4. Global fallbacks

URL Pattern: /api/canvas/<product_code>/<layer>?color=<color>&material=<material>
"""

from flask import Blueprint, send_file, request, jsonify, current_app
import os
from pathlib import Path
import json

canvas_bp = Blueprint('canvas', __name__)

# Load product data to get type/subtype information
def get_product_data():
    """Load product data from JSON file"""
    data_path = os.path.join(current_app.root_path, 'data', 'products.json')
    try:
        with open(data_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except Exception as e:
        current_app.logger.error(f"Error loading product data: {e}")
        return []

def get_product_info(product_code):
    """Get product type, subtype, and other metadata"""
    products = get_product_data()
    for product in products:
        if product.get('productCode') == product_code or product.get('id') == product_code:
            base_type = product.get('baseType', '').lower()
            sub_type = None
            
            # Extract subtype
            subtype_obj = product.get('subType', {})
            if isinstance(subtype_obj, dict):
                if subtype_obj.get('door'):
                    sub_type = subtype_obj['door'].lower().replace(' ', '-')
                elif subtype_obj.get('window'):
                    sub_type = subtype_obj['window'].lower().replace(' ', '-')
            
            return {
                'code': product_code,
                'type': base_type,
                'subtype': sub_type,
                'colors': product.get('colors', []),
                'materials': product.get('materials', [])
            }
    return None

def find_image_with_fallback(product_code, layer, color=None, material=None):
    """
    Find image using hierarchical fallback system.
    
    Priority order:
    1. /images/<type>/<subtype>/<code>/<layer>-<color>.<ext>
    2. /images/<type>/<subtype>/<code>/<layer>.<ext>
    3. /images/<type>/<subtype>/layers/<layer>-<color>.<ext>
    4. /images/<type>/<subtype>/layers/<layer>.<ext>
    5. /images/<type>/layers/<layer>.<ext>
    6. /images/layers/<layer>.<ext>
    
    Returns: (file_path, mime_type) or (None, None)
    """
    product_info = get_product_info(product_code)
    if not product_info:
        current_app.logger.warning(f"Product not found: {product_code}")
        return None, None
    
    images_dir = os.path.join(current_app.root_path, 'static', 'images')
    base_type = product_info['type']
    sub_type = product_info['subtype']
    
    # Supported extensions
    extensions = ['png', 'jpg', 'jpeg', 'webp']
    
    # Build search paths in priority order
    search_paths = []
    
    # 1. Product-specific with color
    if color and base_type and sub_type:
        for ext in extensions:
            search_paths.append(os.path.join(images_dir, base_type, sub_type, product_code, f"{layer}-{color.lower()}.{ext}"))
    
    # 2. Product-specific without color
    if base_type and sub_type:
        for ext in extensions:
            search_paths.append(os.path.join(images_dir, base_type, sub_type, product_code, f"{layer}.{ext}"))
    
    # 3. Subtype fallback with color
    if color and base_type and sub_type:
        for ext in extensions:
            search_paths.append(os.path.join(images_dir, base_type, sub_type, 'layers', f"{layer}-{color.lower()}.{ext}"))
    
    # 4. Subtype fallback without color
    if base_type and sub_type:
        for ext in extensions:
            search_paths.append(os.path.join(images_dir, base_type, sub_type, 'layers', f"{layer}.{ext}"))
    
    # 5. Type fallback
    if base_type:
        for ext in extensions:
            search_paths.append(os.path.join(images_dir, base_type, 'layers', f"{layer}.{ext}"))
    
    # 6. Global fallback
    for ext in extensions:
        search_paths.append(os.path.join(images_dir, 'layers', f"{layer}.{ext}"))
    
    # Search for first existing file
    for path in search_paths:
        if os.path.exists(path):
            # Determine MIME type
            ext = path.split('.')[-1].lower()
            mime_types = {
                'png': 'image/png',
                'jpg': 'image/jpeg',
                'jpeg': 'image/jpeg',
                'webp': 'image/webp'
            }
            mime_type = mime_types.get(ext, 'image/png')
            
            current_app.logger.info(f"Found image: {path}")
            return path, mime_type
    
    current_app.logger.warning(f"No image found for {product_code}/{layer} (color: {color})")
    return None, None

@canvas_bp.route('/api/canvas/<product_code>/<layer>')
def get_layer_image(product_code, layer):
    """
    Serve a specific layer image for a product with hierarchical fallback.
    
    Query parameters:
    - color: Optional color variant
    - material: Optional material (for future use)
    
    Returns: Image file or 404
    """
    color = request.args.get('color')
    material = request.args.get('material')
    
    # Validate layer name (prevent directory traversal)
    valid_layers = ['base', 'door', 'hardware', 'overlay', 'foreground']
    if layer not in valid_layers:
        return jsonify({'error': 'Invalid layer name'}), 400
    
    # Find image with fallback
    image_path, mime_type = find_image_with_fallback(product_code, layer, color, material)
    
    if image_path:
        return send_file(image_path, mimetype=mime_type)
    else:
        # Return placeholder or 404
        return jsonify({
            'error': 'Image not found',
            'product': product_code,
            'layer': layer,
            'color': color
        }), 404

@canvas_bp.route('/api/canvas/<product_code>/info')
def get_canvas_info(product_code):
    """
    Get information about available layers for a product.
    Useful for frontend to know which layers exist.
    """
    product_info = get_product_info(product_code)
    
    if not product_info:
        return jsonify({'error': 'Product not found'}), 404
    
    # Check which layers are available
    available_layers = {}
    layers_to_check = ['base', 'door', 'hardware', 'overlay', 'foreground']
    
    for layer in layers_to_check:
        # Check if layer exists (with or without color)
        path, _ = find_image_with_fallback(product_code, layer)
        if path:
            available_layers[layer] = True
            
            # For door layer, check which colors are available
            if layer == 'door' and product_info['colors']:
                available_colors = []
                for color in product_info['colors']:
                    color_path, _ = find_image_with_fallback(product_code, layer, color)
                    if color_path:
                        available_colors.append(color)
                available_layers['door_colors'] = available_colors
    
    return jsonify({
        'product': product_code,
        'type': product_info['type'],
        'subtype': product_info['subtype'],
        'availableLayers': available_layers,
        'colors': product_info['colors'],
        'materials': product_info['materials']
    })

@canvas_bp.route('/api/canvas/test')
def test_canvas():
    """Test endpoint to verify canvas API is working"""
    return jsonify({
        'status': 'ok',
        'message': 'Canvas API is running',
        'endpoints': {
            'get_layer': '/api/canvas/<product_code>/<layer>?color=<color>',
            'get_info': '/api/canvas/<product_code>/info',
            'test': '/api/canvas/test'
        }
    })
