"""Generate UI tab markdown content from parsed YAML blocks."""

from typing import Any

from .i18n_loader import get_field_description, get_field_label, get_value_label
from .nav_map import ALL_CONFIG_SECTIONS, detect_level, get_nav_path
from .schema_loader import is_boolean_field, is_object_field
from .section_config_parser import get_hidden_fields
from .yaml_extractor import YamlBlock, get_leaf_paths


def _format_value(
    value: object,
    field_schema: dict[str, Any] | None,
    i18n: dict[str, Any] | None = None,
) -> str:
    """Format a YAML value for UI display.

    Looks up i18n labels for enum/option values when available.
    """
    if field_schema and is_boolean_field(field_schema):
        return "on" if value else "off"
    if isinstance(value, bool):
        return "on" if value else "off"
    if isinstance(value, list):
        if len(value) == 0:
            return "an empty list"
        items = []
        for v in value:
            label = get_value_label(i18n, str(v)) if i18n else None
            items.append(f"`{label}`" if label else f"`{v}`")
        return ", ".join(items)
    if value is None:
        return "empty"

    # Try i18n label for the raw value (enum translations)
    if i18n and isinstance(value, str):
        label = get_value_label(i18n, value)
        if label:
            return f"`{label}`"

    return f"`{value}`"


def _build_field_label(
    i18n: dict[str, Any],
    section_key: str,
    field_path: list[str],
    level: str,
) -> str:
    """Build the display label for a field using i18n labels.

    For a path like ["continuous", "days"], produces
    "Continuous retention > Retention days" using the actual i18n labels.
    """
    parts: list[str] = []

    for depth in range(len(field_path)):
        sub_path = field_path[: depth + 1]
        label = get_field_label(i18n, section_key, sub_path, level)

        if label:
            parts.append(label)
        else:
            # Fallback to title-cased field name
            parts.append(field_path[depth].replace("_", " ").title())

    return " > ".join(parts)


def _is_hidden(
    field_key: str,
    full_path: list[str],
    hidden_fields: set[str],
) -> bool:
    """Check if a field should be hidden from UI output."""
    # Check exact match
    if field_key in hidden_fields:
        return True

    # Check dotted path match (e.g., "alerts.enabled_in_config")
    dotted = ".".join(str(p) for p in full_path)
    if dotted in hidden_fields:
        return True

    # Check wildcard patterns (e.g., "filters.*.mask")
    for pattern in hidden_fields:
        if "*" in pattern:
            parts = pattern.split(".")
            if len(parts) == len(full_path):
                match = all(
                    p == "*" or p == fp for p, fp in zip(parts, full_path)
                )
                if match:
                    return True

    return False


def generate_ui_content(
    block: YamlBlock,
    schema: dict[str, Any],
    i18n: dict[str, Any],
    section_configs: dict[str, dict[str, Any]],
) -> str | None:
    """Generate UI tab markdown content for a YAML block.

    Args:
        block: Parsed YAML block from a doc file
        schema: Full JSON schema
        i18n: Loaded i18n translations
        section_configs: Parsed section config data

    Returns:
        Generated markdown string for the UI tab, or None if the block
        can't be converted (not a config block, etc.)
    """
    if block.section_key is None:
        return None

    # Determine which config data to walk
    if block.is_camera_level:
        # Camera-level: unwrap cameras.{name}.{section}
        cam_data = block.parsed.get("cameras", {})
        cam_name = block.camera_name or next(iter(cam_data), None)
        if not cam_name:
            return None
        inner = cam_data.get(cam_name, {})
        if not isinstance(inner, dict):
            return None
        level = "camera"
    else:
        inner = block.parsed
        # Determine level from section key
        level = detect_level(block.section_key)

    # Collect sections to process (may span multiple top-level keys)
    sections_to_process: list[tuple[str, dict]] = []
    for key in inner:
        if key in ALL_CONFIG_SECTIONS or key == block.section_key:
            val = inner[key]
            if isinstance(val, dict):
                sections_to_process.append((key, val))
            else:
                # Simple scalar at section level (e.g., record.enabled = True)
                sections_to_process.append((key, {key: val}))

    # If inner is the section itself (e.g., parsed = {"record": {...}})
    if not sections_to_process and block.section_key in inner:
        section_data = inner[block.section_key]
        if isinstance(section_data, dict):
            sections_to_process = [(block.section_key, section_data)]

    if not sections_to_process:
        # Try treating the whole inner dict as the section data
        sections_to_process = [(block.section_key, inner)]

    # Choose pattern based on whether YAML has comments (descriptive) or values
    use_table = block.has_comments

    lines: list[str] = []
    step_num = 1

    for section_key, section_data in sections_to_process:
        # Get navigation path
        i18n_level = "cameras" if level == "camera" else "global"
        nav_path = get_nav_path(section_key, level)
        if nav_path is None:
            # Try global as fallback
            nav_path = get_nav_path(section_key, "global")
        if nav_path is None:
            continue

        # Get hidden fields for this section
        hidden = get_hidden_fields(section_configs, section_key, level)

        # Get leaf paths from the YAML data
        leaves = get_leaf_paths(section_data)

        # Filter out hidden fields
        visible_leaves: list[tuple[tuple[str, ...], object]] = []
        for path, value in leaves:
            path_list = list(path)
            if not _is_hidden(path_list[-1], path_list, hidden):
                visible_leaves.append((path, value))

        if not visible_leaves:
            continue

        if use_table:
            # Pattern A: Field table with descriptions
            lines.append(
                f'Navigate to <NavPath path="{nav_path}" />.'
            )
            lines.append("")
            lines.append("| Field | Description |")
            lines.append("|-------|-------------|")

            for path, _value in visible_leaves:
                path_list = list(path)
                label = _build_field_label(
                    i18n, section_key, path_list, i18n_level
                )
                desc = get_field_description(
                    i18n, section_key, path_list, i18n_level
                )
                if not desc:
                    desc = ""
                lines.append(f"| **{label}** | {desc} |")
        else:
            # Pattern B: Set instructions
            multi_section = len(sections_to_process) > 1

            if multi_section:
                camera_note = ""
                if block.is_camera_level:
                    camera_note = (
                        " and select your camera"
                    )
                lines.append(
                    f'{step_num}. Navigate to <NavPath path="{nav_path}" />{camera_note}.'
                )
            else:
                if block.is_camera_level:
                    lines.append(
                        f'1. Navigate to <NavPath path="{nav_path}" /> and select your camera.'
                    )
                else:
                    lines.append(
                        f'Navigate to <NavPath path="{nav_path}" />.'
                    )
                    lines.append("")

            from .schema_loader import get_field_info

            for path, value in visible_leaves:
                path_list = list(path)
                label = _build_field_label(
                    i18n, section_key, path_list, i18n_level
                )
                field_info = get_field_info(schema, section_key, path_list)
                formatted = _format_value(value, field_info, i18n)

                if multi_section or block.is_camera_level:
                    lines.append(f"   - Set **{label}** to {formatted}")
                else:
                    lines.append(f"- Set **{label}** to {formatted}")

            step_num += 1

    if not lines:
        return None

    return "\n".join(lines)


def wrap_with_config_tabs(ui_content: str, yaml_raw: str, highlight: str | None = None) -> str:
    """Wrap UI content and YAML in ConfigTabs markup.

    Args:
        ui_content: Generated UI tab markdown
        yaml_raw: Original YAML text
        highlight: Optional highlight spec (e.g., "{3-4}")

    Returns:
        Full ConfigTabs MDX block
    """
    highlight_str = f" {highlight}" if highlight else ""

    return f"""<ConfigTabs>
<TabItem value="ui">

{ui_content}

</TabItem>
<TabItem value="yaml">

```yaml{highlight_str}
{yaml_raw}
```

</TabItem>
</ConfigTabs>"""