"""
Image Annotation Layout

Generates a form interface for annotating images with:
- Bounding boxes (rectangular regions)
- Polygons (arbitrary shapes)
- Freeform drawing (brush strokes)
- Landmarks (point annotations)

Uses Fabric.js for canvas-based annotation with zoom/pan support.
"""

import logging
import json
from .identifier_utils import (
    safe_generate_layout,
    escape_html_content
)

logger = logging.getLogger(__name__)

# Default colors for labels if not specified
DEFAULT_COLORS = [
    "#FF6B6B",  # Red
    "#4ECDC4",  # Teal
    "#45B7D1",  # Blue
    "#96CEB4",  # Green
    "#FFEAA7",  # Yellow
    "#DDA0DD",  # Plum
    "#98D8C8",  # Mint
    "#F7DC6F",  # Gold
    "#BB8FCE",  # Purple
    "#85C1E9",  # Light Blue
]

# Valid annotation tools
VALID_TOOLS = ["bbox", "polygon", "freeform", "landmark", "fill", "eraser", "brush"]


def generate_image_annotation_layout(annotation_scheme):
    """
    Generate HTML for an image annotation interface.

    Args:
        annotation_scheme (dict): Configuration including:
            - name: Schema identifier
            - description: Display description
            - tools: List of tools to enable (bbox, polygon, freeform, landmark)
            - labels: List of label definitions with name and optional color
            - zoom_enabled: Whether to enable zoom (default: True)
            - pan_enabled: Whether to enable pan (default: True)
            - min_annotations: Minimum required annotations (default: 0)
            - max_annotations: Maximum allowed annotations (default: null/unlimited)
            - freeform_brush_size: Brush size for freeform tool (default: 5)
            - freeform_simplify: Whether to simplify freeform paths (default: True)

    Returns:
        tuple: (html_string, key_bindings)
            html_string: Complete HTML for the image annotation interface
            key_bindings: List of keyboard shortcuts

    Raises:
        ValueError: If required fields are missing or invalid
    """
    return safe_generate_layout(annotation_scheme, _generate_image_annotation_layout_internal)


def _generate_image_annotation_layout_internal(annotation_scheme):
    """
    Internal function to generate image annotation layout after validation.
    """
    schema_name = annotation_scheme.get('name', 'image_annotation')
    logger.debug(f"Generating image annotation layout for schema: {schema_name}")

    # Validate required fields
    if "labels" not in annotation_scheme:
        error_msg = f"Missing labels in schema: {schema_name}"
        logger.error(error_msg)
        raise ValueError(error_msg)

    if "tools" not in annotation_scheme:
        error_msg = f"Missing tools in schema: {schema_name}"
        logger.error(error_msg)
        raise ValueError(error_msg)

    # Validate tools
    tools = annotation_scheme["tools"]
    if not isinstance(tools, list) or not tools:
        error_msg = f"tools must be a non-empty list in schema: {schema_name}"
        logger.error(error_msg)
        raise ValueError(error_msg)

    invalid_tools = [t for t in tools if t not in VALID_TOOLS]
    if invalid_tools:
        error_msg = f"Invalid tools: {invalid_tools}. Valid tools are: {VALID_TOOLS}"
        logger.error(error_msg)
        raise ValueError(error_msg)

    # Process labels with colors
    labels = _process_labels(annotation_scheme["labels"])

    # Get configuration options
    zoom_enabled = annotation_scheme.get("zoom_enabled", True)
    pan_enabled = annotation_scheme.get("pan_enabled", True)
    min_annotations = annotation_scheme.get("min_annotations", 0)
    max_annotations = annotation_scheme.get("max_annotations", None)
    freeform_brush_size = annotation_scheme.get("freeform_brush_size", 5)
    freeform_simplify = annotation_scheme.get("freeform_simplify", True)

    # Segmentation mask configuration
    brush_size = annotation_scheme.get("brush_size", 20)
    eraser_size = annotation_scheme.get("eraser_size", 20)
    mask_opacity = annotation_scheme.get("mask_opacity", 0.5)

    # AI support configuration
    ai_support = annotation_scheme.get("ai_support", {})
    ai_enabled = ai_support.get("enabled", False)

    # source_field: Links this annotation schema to a display field from instance_display
    source_field = annotation_scheme.get("source_field", "")

    # Build config object for JavaScript
    js_config = {
        "schemaName": schema_name,
        "tools": tools,
        "labels": labels,
        "zoomEnabled": zoom_enabled,
        "panEnabled": pan_enabled,
        "minAnnotations": min_annotations,
        "maxAnnotations": max_annotations,
        "freeformBrushSize": freeform_brush_size,
        "freeformSimplify": freeform_simplify,
        "brushSize": brush_size,
        "eraserSize": eraser_size,
        "maskOpacity": mask_opacity,
        "aiSupport": ai_enabled,
        "aiFeatures": ai_support.get("features", {}) if ai_enabled else {},
        "sourceField": source_field,
    }

    # Generate HTML
    html = _generate_html(annotation_scheme, js_config, schema_name, labels, tools, ai_enabled, ai_support)

    # Generate keybindings
    keybindings = _generate_keybindings(labels, tools)

    logger.info(f"Successfully generated image annotation layout for {schema_name}")
    return html, keybindings


def _process_labels(labels_config):
    """
    Process label configuration and assign colors.

    Args:
        labels_config: List of label configs (strings or dicts)

    Returns:
        List of processed label dicts with name, color, and optional key_value
    """
    processed = []
    for i, label in enumerate(labels_config):
        if isinstance(label, str):
            processed.append({
                "name": label,
                "color": DEFAULT_COLORS[i % len(DEFAULT_COLORS)],
            })
        elif isinstance(label, dict):
            processed.append({
                "name": label.get("name", f"label_{i}"),
                "color": label.get("color", DEFAULT_COLORS[i % len(DEFAULT_COLORS)]),
                "key_value": label.get("key_value"),
            })
        else:
            processed.append({
                "name": str(label),
                "color": DEFAULT_COLORS[i % len(DEFAULT_COLORS)],
            })
    return processed


def _generate_html(annotation_scheme, js_config, schema_name, labels, tools, ai_enabled=False, ai_support=None):
    """
    Generate the HTML for the image annotation interface.
    """
    escaped_name = escape_html_content(schema_name)
    description = escape_html_content(annotation_scheme.get('description', ''))
    config_json = json.dumps(js_config)

    # source_field attribute for linking to display fields
    source_field = annotation_scheme.get("source_field", "")
    source_field_attr = f' data-source-field="{escape_html_content(source_field)}"' if source_field else ""

    # Generate tool buttons
    tool_buttons = _generate_tool_buttons(tools)

    # Generate label selector
    label_selector = _generate_label_selector(labels)

    # Generate AI toolbar if enabled
    ai_toolbar_html = ""
    ai_init_script = ""
    if ai_enabled:
        ai_features = ai_support.get("features", {}) if ai_support else {}
        ai_toolbar_html = _generate_ai_toolbar(ai_features)
        ai_init_script = _generate_ai_init_script(escaped_name)

    html = f'''
    <form id="{escaped_name}" class="annotation-form image-annotation" action="/action_page.php"{source_field_attr}>
        <fieldset schema="{escaped_name}">
            <legend>{description}</legend>

            <!-- Image Annotation Container -->
            <div class="image-annotation-container" data-schema="{escaped_name}" data-ai-enabled="{str(ai_enabled).lower()}">
                <!-- Toolbar -->
                <div class="image-annotation-toolbar">
                    <!-- Tool buttons -->
                    <div class="tool-group">
                        <span class="tool-group-label">Tools:</span>
                        {tool_buttons}
                    </div>

                    <!-- Label selector -->
                    <div class="label-group">
                        <span class="tool-group-label">Label:</span>
                        {label_selector}
                    </div>

                    <!-- Zoom controls -->
                    <div class="zoom-group">
                        <button type="button" class="zoom-btn" data-action="zoom-in" title="Zoom In (+)">+</button>
                        <button type="button" class="zoom-btn" data-action="zoom-out" title="Zoom Out (-)">-</button>
                        <button type="button" class="zoom-btn" data-action="zoom-fit" title="Fit to View (0)">Fit</button>
                        <button type="button" class="zoom-btn" data-action="zoom-reset" title="Reset Zoom">100%</button>
                    </div>

                    <!-- Edit controls -->
                    <div class="edit-group">
                        <button type="button" class="edit-btn" data-action="undo" title="Undo (Ctrl+Z)">Undo</button>
                        <button type="button" class="edit-btn" data-action="redo" title="Redo (Ctrl+Shift+Z)">Redo</button>
                        <button type="button" class="edit-btn delete-btn" data-action="delete" title="Delete Selected (Del)">Delete</button>
                    </div>

                    <!-- Brush size control (shown when brush/eraser selected) -->
                    <div class="brush-size-group" style="display: none;">
                        <span class="tool-group-label">Size:</span>
                        <input type="range" class="brush-size-slider" min="1" max="100" value="20" title="Brush Size">
                        <span class="brush-size-value">20</span>
                    </div>

                    <!-- Annotation count -->
                    <div class="count-group">
                        <span class="annotation-count">Annotations: <span class="count-value">0</span></span>
                    </div>
                </div>

                {ai_toolbar_html}

                <!-- Canvas wrapper -->
                <div class="canvas-wrapper">
                    <canvas id="canvas-{escaped_name}" class="annotation-canvas"></canvas>
                    <!-- Mask canvas for segmentation (overlaid on top) -->
                    <canvas id="mask-canvas-{escaped_name}" class="mask-canvas" style="display: none;"></canvas>
                </div>

                <!-- Hidden input for storing annotation data -->
                <input type="hidden"
                       name="{escaped_name}"
                       id="input-{escaped_name}"
                       class="annotation-data-input"
                       value="">
                <!-- Hidden input for storing mask data (RLE encoded) -->
                <input type="hidden"
                       name="{escaped_name}_masks"
                       id="mask-input-{escaped_name}"
                       class="mask-data-input"
                       value="">
            </div>

            <!-- Initialize the annotation manager -->
            <script>
                (function() {{
                    // Wait for DOM and dependencies
                    function initWhenReady() {{
                        if (typeof ImageAnnotationManager === 'undefined') {{
                            setTimeout(initWhenReady, 100);
                            return;
                        }}
                        var container = document.querySelector('.image-annotation-container[data-schema="{escaped_name}"]');
                        if (!container) return;

                        var config = {config_json};
                        var canvasId = 'canvas-{escaped_name}';
                        var inputId = 'input-{escaped_name}';

                        // Get image URL from the instance display
                        // Priority: 1) data-image-url on #text-content, 2) img src, 3) text content itself
                        var instanceContainer = document.getElementById('instance-text');
                        console.log('[ImageAnnotation] Instance container:', instanceContainer);
                        var textContent = instanceContainer ? instanceContainer.querySelector('#text-content') : null;
                        console.log('[ImageAnnotation] Text content element:', textContent);

                        var imageUrl = null;

                        // Method 1: Check data-image-url attribute (set by template when has_image_annotation=true)
                        if (textContent) {{
                            imageUrl = textContent.getAttribute('data-image-url');
                            if (imageUrl) {{
                                console.log('[ImageAnnotation] Found URL from data-image-url:', imageUrl);
                            }}
                        }}

                        // Method 2: Fallback to looking for an img element with data-source-url or src
                        if (!imageUrl && instanceContainer) {{
                            var imgElement = instanceContainer.querySelector('img');
                            if (imgElement) {{
                                imageUrl = imgElement.getAttribute('data-source-url') || imgElement.src;
                                console.log('[ImageAnnotation] Found URL from img element:', imageUrl);
                            }}
                        }}

                        // Method 3: If text content looks like a URL, use it directly
                        if (!imageUrl && textContent) {{
                            var textVal = textContent.textContent.trim();
                            if (textVal.match(/^https?:\/\/.+\.(jpg|jpeg|png|gif|webp|svg)/i)) {{
                                imageUrl = textVal;
                                console.log('[ImageAnnotation] Found URL from text content:', imageUrl);
                            }}
                        }}

                        // Method 4: Check source_field in instance data (via display fields)
                        if (!imageUrl && config.sourceField) {{
                            var displayFields = document.querySelectorAll('[data-field-key="' + config.sourceField + '"]');
                            displayFields.forEach(function(field) {{
                                var url = field.getAttribute('data-source-url') || field.getAttribute('src');
                                if (url && !imageUrl) {{
                                    imageUrl = url;
                                    console.log('[ImageAnnotation] Found URL from source_field display:', imageUrl);
                                }}
                            }});
                        }}

                        if (!imageUrl) {{
                            console.error('[ImageAnnotation] No image URL found! Check that the instance data contains an image URL.');
                        }}

                        // Initialize manager
                        console.log('Initializing ImageAnnotationManager with canvas:', canvasId);
                        var manager = new ImageAnnotationManager(canvasId, inputId, config);

                        // Store reference on container
                        container.annotationManager = manager;

                        // Load image if available
                        if (imageUrl) {{
                            console.log('Calling loadImage with:', imageUrl);
                            manager.loadImage(imageUrl);
                        }} else {{
                            console.warn('No image URL found for annotation');
                        }}

                        // Wire up toolbar buttons
                        container.querySelectorAll('.tool-btn').forEach(function(btn) {{
                            btn.addEventListener('click', function() {{
                                var tool = this.dataset.tool;
                                manager.setTool(tool);
                                container.querySelectorAll('.tool-btn').forEach(function(b) {{
                                    b.classList.remove('active');
                                }});
                                this.classList.add('active');

                                // Show/hide brush size control for brush/eraser tools
                                var brushSizeGroup = container.querySelector('.brush-size-group');
                                if (brushSizeGroup) {{
                                    brushSizeGroup.style.display = (tool === 'brush' || tool === 'eraser') ? 'flex' : 'none';
                                }}
                            }});
                        }});

                        // Wire up brush size slider
                        var brushSlider = container.querySelector('.brush-size-slider');
                        var brushSizeValue = container.querySelector('.brush-size-value');
                        if (brushSlider) {{
                            brushSlider.addEventListener('input', function() {{
                                var size = parseInt(this.value);
                                if (brushSizeValue) brushSizeValue.textContent = size;
                                manager.setBrushSize(size);
                            }});
                        }}

                        container.querySelectorAll('.label-btn').forEach(function(btn) {{
                            btn.addEventListener('click', function() {{
                                var label = this.dataset.label;
                                var color = this.dataset.color;
                                manager.setLabel(label, color);
                                container.querySelectorAll('.label-btn').forEach(function(b) {{
                                    b.classList.remove('active');
                                }});
                                this.classList.add('active');
                            }});
                        }});

                        container.querySelectorAll('.zoom-btn').forEach(function(btn) {{
                            btn.addEventListener('click', function() {{
                                var action = this.dataset.action;
                                if (action === 'zoom-in') manager.zoom(1.2);
                                else if (action === 'zoom-out') manager.zoom(0.8);
                                else if (action === 'zoom-fit') manager.zoomFit();
                                else if (action === 'zoom-reset') manager.zoomReset();
                            }});
                        }});

                        container.querySelectorAll('.edit-btn').forEach(function(btn) {{
                            btn.addEventListener('click', function() {{
                                var action = this.dataset.action;
                                if (action === 'undo') manager.undo();
                                else if (action === 'redo') manager.redo();
                                else if (action === 'delete') manager.deleteSelected();
                            }});
                        }});

                        // Set default tool and label
                        var firstToolBtn = container.querySelector('.tool-btn');
                        if (firstToolBtn) firstToolBtn.click();
                        var firstLabelBtn = container.querySelector('.label-btn');
                        if (firstLabelBtn) firstLabelBtn.click();

                        // Update count display
                        manager.onAnnotationChange = function(count) {{
                            var countEl = container.querySelector('.count-value');
                            if (countEl) countEl.textContent = count;
                        }};

                        {ai_init_script}
                    }}

                    if (document.readyState === 'loading') {{
                        document.addEventListener('DOMContentLoaded', initWhenReady);
                    }} else {{
                        initWhenReady();
                    }}
                }})();
            </script>
        </fieldset>
    </form>
    '''

    return html


def _generate_ai_toolbar(ai_features):
    """
    Generate HTML for the AI assistance toolbar.
    """
    # Determine which buttons to show based on features
    detection_enabled = ai_features.get("detection", True)
    pre_annotate_enabled = ai_features.get("pre_annotate", True)
    classification_enabled = ai_features.get("classification", False)
    hint_enabled = ai_features.get("hint", True)

    buttons = []

    if detection_enabled:
        buttons.append(
            '<button type="button" class="ai-btn" data-action="detect" title="Detect objects in the image">'
            '<span class="ai-btn-icon">🔍</span> Detect</button>'
        )

    if pre_annotate_enabled:
        buttons.append(
            '<button type="button" class="ai-btn" data-action="pre_annotate" title="Auto-detect and pre-annotate all objects">'
            '<span class="ai-btn-icon">⚡</span> Auto</button>'
        )

    if classification_enabled:
        buttons.append(
            '<button type="button" class="ai-btn" data-action="classification" title="Classify selected region">'
            '<span class="ai-btn-icon">🏷️</span> Classify</button>'
        )

    if hint_enabled:
        buttons.append(
            '<button type="button" class="ai-btn" data-action="hint" title="Get a hint for annotation">'
            '<span class="ai-btn-icon">💡</span> Hint</button>'
        )

    if not buttons:
        return ""

    return f'''
                <!-- AI Assistance Toolbar -->
                <div class="ai-toolbar">
                    <div class="ai-toolbar-group">
                        <span class="ai-toolbar-label">AI Assist:</span>
                        {" ".join(buttons)}
                    </div>
                    <div class="ai-suggestion-controls" style="display: none;">
                        <span class="suggestion-count">0 suggestions</span>
                        <button type="button" class="ai-btn ai-btn-accept" data-action="accept-all" title="Accept all suggestions">
                            Accept All
                        </button>
                        <button type="button" class="ai-btn ai-btn-clear" data-action="clear" title="Clear all suggestions">
                            Clear
                        </button>
                    </div>
                    <div class="ai-loading-indicator" style="display: none;">
                        <span class="spinner"></span> Loading...
                    </div>
                </div>
                <!-- AI Tooltip Container -->
                <div class="ai-tooltip-container" style="display: none;"></div>
    '''


def _generate_ai_init_script(escaped_name):
    """
    Generate JavaScript initialization code for AI assistant.
    """
    return f'''
                        // Initialize AI assistant if enabled and VisualAIAssistantManager is available
                        if (config.aiSupport && typeof VisualAIAssistantManager !== 'undefined') {{
                            var annotationId = Array.from(document.querySelectorAll('.annotation-form')).indexOf(
                                document.getElementById('{escaped_name}')
                            );
                            container.aiAssistant = new VisualAIAssistantManager({{
                                annotationType: 'image_annotation',
                                annotationId: annotationId >= 0 ? annotationId : 0,
                                annotationManager: manager
                            }});
                        }}
    '''


def _generate_tool_buttons(tools):
    """
    Generate HTML for tool selection buttons.
    """
    tool_info = {
        "bbox": {"label": "Box", "title": "Bounding Box (B)", "icon": "□"},
        "polygon": {"label": "Polygon", "title": "Polygon (P)", "icon": "⬡"},
        "freeform": {"label": "Draw", "title": "Freeform Draw (F)", "icon": "✎"},
        "landmark": {"label": "Point", "title": "Landmark Point (L)", "icon": "◉"},
        "brush": {"label": "Brush", "title": "Segmentation Brush (M)", "icon": "🖌️"},
        "fill": {"label": "Fill", "title": "Flood Fill (G)", "icon": "🪣"},
        "eraser": {"label": "Eraser", "title": "Eraser (E)", "icon": "⌫"},
    }

    buttons = []
    for tool in tools:
        info = tool_info.get(tool, {"label": tool, "title": tool, "icon": "?"})
        buttons.append(
            f'<button type="button" class="tool-btn" data-tool="{tool}" title="{info["title"]}">'
            f'{info["icon"]} {info["label"]}</button>'
        )

    return "\n".join(buttons)


def _generate_label_selector(labels):
    """
    Generate HTML for label selection buttons.
    """
    buttons = []
    for label in labels:
        name = escape_html_content(label["name"])
        color = label["color"]
        key_hint = f' ({label["key_value"]})' if label.get("key_value") else ""
        buttons.append(
            f'<button type="button" class="label-btn" data-label="{name}" data-color="{color}" '
            f'title="{name}{key_hint}" style="--label-color: {color};">'
            f'<span class="label-color-dot" style="background-color: {color};"></span>'
            f'{name}</button>'
        )

    return "\n".join(buttons)


def _generate_keybindings(labels, tools):
    """
    Generate keybinding list for the schema.
    """
    keybindings = []

    # Tool shortcuts
    tool_keys = {
        "bbox": ("b", "Bounding Box tool"),
        "polygon": ("p", "Polygon tool"),
        "freeform": ("f", "Freeform draw tool"),
        "landmark": ("l", "Landmark point tool"),
        "brush": ("m", "Segmentation brush tool"),
        "fill": ("g", "Flood fill tool"),
        "eraser": ("e", "Eraser tool"),
    }
    for tool in tools:
        if tool in tool_keys:
            keybindings.append(tool_keys[tool])

    # Label shortcuts
    for label in labels:
        if label.get("key_value"):
            keybindings.append((label["key_value"], f"Select label: {label['name']}"))

    # Common shortcuts
    keybindings.extend([
        ("Del", "Delete selected"),
        ("+/-", "Zoom in/out"),
        ("0", "Fit to view"),
    ])

    return keybindings
