"""
Shared UI utilities for FastMCP HTML pages.

This module provides reusable HTML/CSS components for OAuth callbacks,
consent pages, and other user-facing interfaces.
"""

from __future__ import annotations

import html

from starlette.responses import HTMLResponse

# FastMCP branding
FASTMCP_LOGO_URL = "https://gofastmcp.com/assets/brand/blue-logo.png"

# Base CSS styles shared across all FastMCP pages
BASE_STYLES = """
    * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }

    body {
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
        margin: 0;
        padding: 0;
        min-height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        background: #f9fafb;
        color: #0a0a0a;
    }

    .container {
        background: #ffffff;
        border: 1px solid #e5e7eb;
        padding: 3rem 2.5rem;
        border-radius: 1rem;
        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        text-align: center;
        max-width: 36rem;
        margin: 1rem;
        width: 100%;
    }

    @media (max-width: 640px) {
        .container {
            padding: 2rem 1.5rem;
            margin: 0.5rem;
        }
    }

    .logo {
        width: 64px;
        height: auto;
        margin-bottom: 1.5rem;
        display: block;
        margin-left: auto;
        margin-right: auto;
    }

    h1 {
        font-size: 1.5rem;
        font-weight: 600;
        margin-bottom: 1.5rem;
        color: #111827;
    }
"""

# Button styles
BUTTON_STYLES = """
    .button-group {
        display: flex;
        gap: 0.75rem;
        margin-top: 1.5rem;
        justify-content: center;
    }

    button {
        padding: 0.75rem 2rem;
        font-size: 0.9375rem;
        font-weight: 500;
        border-radius: 0.5rem;
        border: none;
        cursor: pointer;
        transition: all 0.15s;
        font-family: inherit;
    }

    button:hover {
        transform: translateY(-1px);
        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
    }

    .btn-approve, .btn-primary {
        background: #10b981;
        color: #ffffff;
        min-width: 120px;
    }

    .btn-deny, .btn-secondary {
        background: #6b7280;
        color: #ffffff;
        min-width: 120px;
    }
"""

# Info box / message box styles
INFO_BOX_STYLES = """
    .info-box {
        background: #f0f9ff;
        border: 1px solid #bae6fd;
        border-radius: 0.5rem;
        padding: 1rem;
        margin-bottom: 1.5rem;
        text-align: left;
        font-size: 0.9375rem;
        line-height: 1.5;
        color: #374151;
    }

    .info-box p {
        margin-bottom: 0.5rem;
    }

    .info-box p:last-child {
        margin-bottom: 0;
    }

    .info-box.centered {
        text-align: center;
    }

    .info-box.error {
        background: #fef2f2;
        border-color: #fecaca;
        color: #991b1b;
    }

    .info-box strong {
        color: #0ea5e9;
        font-weight: 600;
    }

    .info-box .server-name-link {
        color: #0ea5e9;
        text-decoration: underline;
        font-weight: 600;
        cursor: pointer;
        transition: opacity 0.15s;
    }

    .info-box .server-name-link:hover {
        opacity: 0.8;
    }

    /* Monospace info box - gray styling with code font */
    .info-box-mono {
        background: #f9fafb;
        border: 1px solid #e5e7eb;
        border-radius: 0.5rem;
        padding: 0.875rem;
        margin: 1.25rem 0;
        font-size: 0.875rem;
        color: #6b7280;
        font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace;
        text-align: left;
    }

    .info-box-mono.centered {
        text-align: center;
    }

    .info-box-mono.error {
        background: #fef2f2;
        border-color: #fecaca;
        color: #991b1b;
    }

    .info-box-mono strong {
        color: #111827;
        font-weight: 600;
    }

    .warning-box {
        background: #f0f9ff;
        border: 1px solid #bae6fd;
        border-radius: 0.5rem;
        padding: 1rem;
        margin-bottom: 1.5rem;
        text-align: center;
    }

    .warning-box p {
        margin-bottom: 0.5rem;
        line-height: 1.5;
        color: #6b7280;
        font-size: 0.9375rem;
    }

    .warning-box p:last-child {
        margin-bottom: 0;
    }

    .warning-box strong {
        color: #0ea5e9;
        font-weight: 600;
    }

    .warning-box a {
        color: #0ea5e9;
        text-decoration: underline;
        font-weight: 600;
    }

    .warning-box a:hover {
        color: #0284c7;
        text-decoration: underline;
    }
"""

# Status message styles (for success/error indicators)
STATUS_MESSAGE_STYLES = """
    .status-message {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.75rem;
        margin-bottom: 1.5rem;
    }

    .status-icon {
        font-size: 1.5rem;
        line-height: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 2rem;
        height: 2rem;
        border-radius: 0.5rem;
        flex-shrink: 0;
    }

    .status-icon.success {
        background: #10b98120;
    }

    .status-icon.error {
        background: #ef444420;
    }

    .message {
        font-size: 1.125rem;
        line-height: 1.75;
        color: #111827;
        font-weight: 600;
        text-align: left;
    }
"""

# Detail box styles (for key-value pairs)
DETAIL_BOX_STYLES = """
    .detail-box {
        background: #f9fafb;
        border: 1px solid #e5e7eb;
        border-radius: 0.5rem;
        padding: 1rem;
        margin-bottom: 1.5rem;
        text-align: left;
    }

    .detail-row {
        display: flex;
        padding: 0.5rem 0;
        border-bottom: 1px solid #e5e7eb;
    }

    .detail-row:last-child {
        border-bottom: none;
    }

    .detail-label {
        font-weight: 600;
        min-width: 160px;
        color: #6b7280;
        font-size: 0.875rem;
        flex-shrink: 0;
        padding-right: 1rem;
    }

    .detail-value {
        flex: 1;
        font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace;
        font-size: 0.75rem;
        color: #111827;
        word-break: break-all;
        overflow-wrap: break-word;
    }
"""

# Redirect section styles (for OAuth redirect URI box)
REDIRECT_SECTION_STYLES = """
    .redirect-section {
        background: #fffbeb;
        border: 1px solid #fcd34d;
        border-radius: 0.5rem;
        padding: 1rem;
        margin-bottom: 1.5rem;
        text-align: left;
    }

    .redirect-section .label {
        font-size: 0.875rem;
        color: #6b7280;
        font-weight: 600;
        margin-bottom: 0.5rem;
        display: block;
    }

    .redirect-section .value {
        font-family: 'SF Mono', 'Monaco', 'Consolas', 'Courier New', monospace;
        font-size: 0.875rem;
        color: #111827;
        word-break: break-all;
        margin-top: 0.25rem;
    }
"""

# Collapsible details styles
DETAILS_STYLES = """
    details {
        margin-bottom: 1.5rem;
        text-align: left;
    }

    summary {
        cursor: pointer;
        font-size: 0.875rem;
        color: #6b7280;
        font-weight: 600;
        list-style: none;
        padding: 0.5rem;
        border-radius: 0.25rem;
    }

    summary:hover {
        background: #f9fafb;
    }

    summary::marker {
        display: none;
    }

    summary::before {
        content: "▶";
        display: inline-block;
        margin-right: 0.5rem;
        transition: transform 0.2s;
        font-size: 0.75rem;
    }

    details[open] summary::before {
        transform: rotate(90deg);
    }
"""

# Helper text styles
HELPER_TEXT_STYLES = """
    .close-instruction, .help-text {
        font-size: 0.875rem;
        color: #6b7280;
        margin-top: 1.5rem;
    }
"""

# Tooltip styles for hover help
TOOLTIP_STYLES = """
    .help-link-container {
        position: fixed;
        bottom: 1.5rem;
        right: 1.5rem;
        font-size: 0.875rem;
    }

    .help-link {
        color: #6b7280;
        text-decoration: none;
        cursor: help;
        position: relative;
        display: inline-block;
        border-bottom: 1px dotted #9ca3af;
    }

    @media (max-width: 640px) {
        .help-link {
            background: #ffffff;
            padding: 0.25rem 0.5rem;
            border-radius: 0.25rem;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
        }
    }

    .help-link:hover {
        color: #111827;
        border-bottom-color: #111827;
    }

    .help-link:hover .tooltip {
        opacity: 1;
        visibility: visible;
    }

    .tooltip {
        position: absolute;
        bottom: 100%;
        right: 0;
        left: auto;
        margin-bottom: 0.5rem;
        background: #1f2937;
        color: #ffffff;
        padding: 0.75rem 1rem;
        border-radius: 0.5rem;
        font-size: 0.8125rem;
        line-height: 1.5;
        width: 280px;
        max-width: calc(100vw - 3rem);
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.2s, visibility 0.2s;
        box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
        text-align: left;
    }

    .tooltip::after {
        content: '';
        position: absolute;
        top: 100%;
        right: 1rem;
        border: 6px solid transparent;
        border-top-color: #1f2937;
    }

    .tooltip-link {
        color: #60a5fa;
        text-decoration: underline;
    }
"""


def create_page(
    content: str,
    title: str = "FastMCP",
    additional_styles: str = "",
    csp_policy: str = "default-src 'none'; style-src 'unsafe-inline'; img-src https: data:; base-uri 'none'",
) -> str:
    """
    Create a complete HTML page with FastMCP styling.

    Args:
        content: HTML content to place inside the page
        title: Page title
        additional_styles: Extra CSS to include
        csp_policy: Content Security Policy header value.
            If empty string "", the CSP meta tag is omitted entirely.

    Returns:
        Complete HTML page as string
    """
    title = html.escape(title)

    # Only include CSP meta tag if policy is non-empty
    csp_meta = (
        f'<meta http-equiv="Content-Security-Policy" content="{html.escape(csp_policy, quote=True)}" />'
        if csp_policy
        else ""
    )

    return f"""
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{title}</title>
        <style>
            {BASE_STYLES}
            {additional_styles}
        </style>
        {csp_meta}
    </head>
    <body>
        {content}
    </body>
    </html>
    """


def create_logo(icon_url: str | None = None, alt_text: str = "FastMCP") -> str:
    """Create logo HTML.

    Args:
        icon_url: Optional custom icon URL. If not provided, uses the FastMCP logo.
        alt_text: Alt text for the logo image.

    Returns:
        HTML for logo image tag.
    """
    url = icon_url or FASTMCP_LOGO_URL
    alt = html.escape(alt_text)
    return f'<img src="{html.escape(url)}" alt="{alt}" class="logo" />'


def create_status_message(message: str, is_success: bool = True) -> str:
    """
    Create a status message with icon.

    Args:
        message: Status message text
        is_success: True for success (✓), False for error (✕)

    Returns:
        HTML for status message
    """
    message = html.escape(message)
    icon = "✓" if is_success else "✕"
    icon_class = "success" if is_success else "error"

    return f"""
        <div class="status-message">
            <span class="status-icon {icon_class}">{icon}</span>
            <div class="message">{message}</div>
        </div>
    """


def create_info_box(
    content: str,
    is_error: bool = False,
    centered: bool = False,
    monospace: bool = False,
) -> str:
    """
    Create an info box.

    Args:
        content: HTML content for the info box
        is_error: True for error styling, False for normal
        centered: True to center the text, False for left-aligned
        monospace: True to use gray monospace font styling instead of blue

    Returns:
        HTML for info box
    """
    content = html.escape(content)
    base_class = "info-box-mono" if monospace else "info-box"
    classes = [base_class]
    if is_error:
        classes.append("error")
    if centered:
        classes.append("centered")
    class_str = " ".join(classes)
    return f'<div class="{class_str}">{content}</div>'


def create_detail_box(rows: list[tuple[str, str]]) -> str:
    """
    Create a detail box with key-value pairs.

    Args:
        rows: List of (label, value) tuples

    Returns:
        HTML for detail box
    """
    rows_html = "\n".join(
        f"""
        <div class="detail-row">
            <div class="detail-label">{html.escape(label)}:</div>
            <div class="detail-value">{html.escape(value)}</div>
        </div>
        """
        for label, value in rows
    )

    return f'<div class="detail-box">{rows_html}</div>'


def create_button_group(buttons: list[tuple[str, str, str]]) -> str:
    """
    Create a group of buttons.

    Args:
        buttons: List of (text, value, css_class) tuples

    Returns:
        HTML for button group
    """
    buttons_html = "\n".join(
        f'<button type="submit" name="action" value="{value}" class="{css_class}">{text}</button>'
        for text, value, css_class in buttons
    )

    return f'<div class="button-group">{buttons_html}</div>'


def create_secure_html_response(html: str, status_code: int = 200) -> HTMLResponse:
    """
    Create an HTMLResponse with security headers.

    Adds X-Frame-Options: DENY to prevent clickjacking attacks per MCP security best practices.

    Args:
        html: HTML content to return
        status_code: HTTP status code

    Returns:
        HTMLResponse with security headers
    """
    return HTMLResponse(
        content=html,
        status_code=status_code,
        headers={"X-Frame-Options": "DENY"},
    )
