"""
Response formatters for PowerBI data

Converts API responses into user-friendly formats (Markdown, JSON).
"""

from typing import Any, Callable, Optional

from .models import DetailLevel
from .constants import CHARACTER_LIMIT, MAX_ROWS_DISPLAY


def _format_items_markdown(
    items: list[dict[str, Any]],
    item_type: str,
    detail: DetailLevel,
    detail_formatter: Optional[Callable[[dict[str, Any]], list[str]]] = None
) -> str:
    """
    Generic markdown formatter for lists of items (workspaces, datasets, etc.)

    Args:
        items: List of item dictionaries from API
        item_type: Type of items (e.g., "Workspaces", "Datasets")
        detail: Level of detail (concise or detailed)
        detail_formatter: Optional function to format detailed fields for an item

    Returns:
        Markdown-formatted string of items
    """
    if not items:
        return f"No {item_type.lower()} found."

    lines = [f"# PowerBI {item_type} ({len(items)} total)\n"]

    for item in items:
        lines.append(f"## {item.get('name', 'Unnamed')}")
        lines.append(f"- **ID**: `{item.get('id')}`")

        if detail == DetailLevel.DETAILED and detail_formatter:
            detail_lines = detail_formatter(item)
            lines.extend(detail_lines)

        lines.append("")

    return "\n".join(lines)


def _format_workspace_details(ws: dict[str, Any]) -> list[str]:
    """Format detailed fields for a workspace"""
    lines = []
    lines.append(f"- **Type**: {ws.get('type', 'N/A')}")
    lines.append(f"- **State**: {ws.get('state', 'N/A')}")
    if ws.get('isReadOnly'):
        lines.append("- **Read Only**: Yes")
    if ws.get('isOnDedicatedCapacity'):
        lines.append("- **Dedicated Capacity**: Yes")
        if ws.get('capacityId'):
            lines.append(f"- **Capacity ID**: {ws.get('capacityId')}")
    return lines


def _format_dataset_details(ds: dict[str, Any]) -> list[str]:
    """Format detailed fields for a dataset"""
    lines = []
    lines.append(f"- **Configured By**: {ds.get('configuredBy', 'N/A')}")
    if ds.get('isRefreshable'):
        lines.append("- **Refreshable**: Yes")
    if ds.get('isEffectiveIdentityRequired'):
        lines.append("- **Effective Identity Required**: Yes")
    if ds.get('isEffectiveIdentityRolesRequired'):
        lines.append("- **Effective Identity Roles Required**: Yes")
    if ds.get('targetStorageMode'):
        lines.append(f"- **Storage Mode**: {ds.get('targetStorageMode')}")
    if ds.get('createdDate'):
        lines.append(f"- **Created**: {ds.get('createdDate')}")
    return lines


def truncate_response(text: str, limit: int = CHARACTER_LIMIT) -> str:
    """
    Truncate response to character limit

    Args:
        text: Response text to truncate
        limit: Maximum character limit (default: 25000)

    Returns:
        Truncated text with informative message if truncated
    """
    if len(text) <= limit:
        return text

    truncated = text[:limit]
    return (
        f"{truncated}\n\n"
        f"... [Response truncated at {limit} characters. "
        "Use filtering or pagination to reduce response size.]"
    )


def format_workspaces_markdown(workspaces: list[dict[str, Any]], detail: DetailLevel) -> str:
    """
    Format workspaces as markdown

    Args:
        workspaces: List of workspace dictionaries from API
        detail: Level of detail (concise or detailed)

    Returns:
        Markdown-formatted string of workspaces
    """
    return _format_items_markdown(workspaces, "Workspaces", detail, _format_workspace_details)


def format_datasets_markdown(datasets: list[dict[str, Any]], detail: DetailLevel) -> str:
    """
    Format datasets as markdown

    Args:
        datasets: List of dataset dictionaries from API
        detail: Level of detail (concise or detailed)

    Returns:
        Markdown-formatted string of datasets
    """
    return _format_items_markdown(datasets, "Datasets", detail, _format_dataset_details)


def format_dataset_markdown(dataset: dict[str, Any]) -> str:
    """
    Format single dataset details as markdown

    Args:
        dataset: Dataset dictionary from API

    Returns:
        Markdown-formatted string of dataset details
    """
    lines = [f"# Dataset: {dataset.get('name', 'Unnamed')}\n"]

    for key, value in dataset.items():
        # Format key nicely (convert camelCase to Title Case)
        formatted_key = key.replace('_', ' ').title()
        lines.append(f"- **{formatted_key}**: {value}")

    return "\n".join(lines)


def format_query_results_markdown(results: dict[str, Any]) -> str:
    """
    Format query results as markdown tables

    Args:
        results: Query results dictionary from API

    Returns:
        Markdown-formatted string with result tables
    """
    if not results or "results" not in results:
        return "No query results."

    lines = ["# Query Results\n"]

    for idx, result in enumerate(results["results"]):
        lines.append(f"## Query {idx + 1}\n")

        if "tables" not in result or not result["tables"]:
            lines.append("*No data returned*\n")
            continue

        for table_idx, table in enumerate(result["tables"]):
            if table_idx > 0:
                lines.append(f"\n### Table {table_idx + 1}\n")

            rows = table.get("rows", [])

            if not rows:
                lines.append("*No rows returned*\n")
                continue

            # Get column names from first row keys
            columns = list(rows[0].keys()) if rows else []

            # Create markdown table header
            lines.append("| " + " | ".join(columns) + " |")
            lines.append("| " + " | ".join(["---"] * len(columns)) + " |")

            # Add rows (limit to prevent huge responses)
            for row in rows[:MAX_ROWS_DISPLAY]:
                values = [str(row.get(col, "")) for col in columns]
                lines.append("| " + " | ".join(values) + " |")

            if len(rows) > MAX_ROWS_DISPLAY:
                lines.append(
                    f"\n*Showing {MAX_ROWS_DISPLAY} of {len(rows)} rows. "
                    "Query returned more data than displayed.*\n"
                )

    return "\n".join(lines)


def format_refresh_history_markdown(
    refresh_history: list[dict[str, Any]],
    dataset_name: str
) -> str:
    """
    Format refresh history as markdown

    Args:
        refresh_history: List of refresh records from API
        dataset_name: Name of the dataset

    Returns:
        Markdown-formatted string of refresh history
    """
    if not refresh_history:
        return f"# Refresh History - Dataset: {dataset_name}\n\nNo refresh history found."

    lines = [
        f"# Refresh History - Dataset: {dataset_name}",
        f"\n## Recent Refreshes (showing {len(refresh_history)})\n"
    ]

    for idx, refresh in enumerate(refresh_history, 1):
        status = refresh.get("status", "Unknown")
        status_emoji = "✓" if status == "Completed" else "✗" if status == "Failed" else "⏳"

        lines.append(f"### Refresh {idx}")
        lines.append(f"- **Status**: {status} {status_emoji}")

        if refresh.get("startTime"):
            lines.append(f"- **Start**: {refresh['startTime']}")

        if refresh.get("endTime"):
            lines.append(f"- **End**: {refresh['endTime']}")

        if refresh.get("refreshType"):
            lines.append(f"- **Type**: {refresh['refreshType']}")

        if refresh.get("requestId"):
            lines.append(f"- **Request ID**: {refresh['requestId']}")

        # Show error details for failed refreshes
        if status == "Failed" and refresh.get("serviceExceptionJson"):
            lines.append(f"- **Error**: {refresh['serviceExceptionJson']}")

        lines.append("")

    return "\n".join(lines)


def format_parameters_markdown(
    parameters: list[dict[str, Any]],
    dataset_name: str,
    detail: DetailLevel
) -> str:
    """
    Format dataset parameters as markdown

    Args:
        parameters: List of parameter dictionaries from API
        dataset_name: Name of the dataset
        detail: Level of detail (concise or normal)

    Returns:
        Markdown-formatted string of parameters
    """
    if not parameters:
        return f"# Dataset Parameters - {dataset_name}\n\nNo parameters defined for this dataset."

    lines = [f"# Dataset Parameters - {dataset_name}\n"]

    # Add summary statistics
    required_count = sum(1 for p in parameters if p.get("isRequired", False))
    lines.append("## Summary")
    lines.append(f"- Total Parameters: {len(parameters)}")
    lines.append(f"- Required: {required_count}")
    lines.append(f"- Optional: {len(parameters) - required_count}")
    lines.append("\n## Parameters\n")

    # List parameters
    for idx, param in enumerate(parameters, 1):
        name = param.get("name", "Unnamed")
        param_type = param.get("type", "Unknown")
        is_required = param.get("isRequired", False)
        required_str = " *Required*" if is_required else ""

        lines.append(f"### {idx}. {name} ({param_type}){required_str}")

        if detail == DetailLevel.CONCISE:
            current_value = param.get("currentValue")
            if current_value is not None:
                lines.append(f"- **Current Value**: {current_value}")
        else:
            # Normal detail - show more info
            current_value = param.get("currentValue")
            if current_value is not None:
                lines.append(f"- **Current Value**: {current_value}")

            suggested = param.get("suggestedValues")
            if suggested:
                values_str = ", ".join(str(v) for v in suggested)
                lines.append(f"- **Suggested Values**: {values_str}")

            description = param.get("description")
            if description:
                lines.append(f"- **Description**: {description}")

        lines.append("")

    return "\n".join(lines)


def format_reports_markdown(
    reports: list[dict[str, Any]],
    workspace_name: str,
    detail: DetailLevel
) -> str:
    """
    Format reports as markdown

    Args:
        reports: List of report dictionaries from API
        workspace_name: Name of the workspace (or "My workspace")
        detail: Level of detail (concise or normal)

    Returns:
        Markdown-formatted string of reports
    """
    if not reports:
        return f"# PowerBI Reports\n\n## Workspace: {workspace_name}\n\nNo reports found."

    lines = [
        "# PowerBI Reports",
        f"\n## Workspace: {workspace_name}",
        f"\nFound {len(reports)} reports:\n"
    ]

    for idx, report in enumerate(reports, 1):
        name = report.get("name", "Unnamed")
        report_id = report.get("id", "N/A")

        if detail == DetailLevel.CONCISE:
            lines.append(f"{idx}. **{name}**")
            lines.append(f"   - ID: {report_id}")
            lines.append("")
        else:
            # Normal detail - show more info
            lines.append(f"### {idx}. {name}")
            lines.append(f"- **Report ID**: {report_id}")

            dataset_id = report.get("datasetId")
            if dataset_id:
                lines.append(f"- **Dataset ID**: {dataset_id}")

            web_url = report.get("webUrl")
            if web_url:
                lines.append(f"- **Web URL**: {web_url}")

            embed_url = report.get("embedUrl")
            if embed_url:
                lines.append(f"- **Embed URL**: {embed_url}")

            lines.append("")

    return "\n".join(lines)
