"""GitHub issue creation utilities for the Modbus diagnostic CLI tool.

Generates issue body and `gh` CLI commands for easy bug reporting.
"""

from __future__ import annotations

import shlex
from pathlib import Path

from pylxpweb.cli.formatters.base import DiagnosticData
from pylxpweb.cli.utils.sanitize import sanitize_serial as _sanitize_serial_impl


def generate_issue_body(
    data: DiagnosticData,
    description: str = "",
    sanitize: bool = True,
) -> str:
    """Generate GitHub issue body markdown.

    Args:
        data: Diagnostic data to include
        description: User-provided issue description
        sanitize: Whether to mask sensitive data

    Returns:
        Markdown-formatted issue body
    """
    lines = [
        "## Description",
        "",
        description or "_Please describe the issue you are experiencing._",
        "",
        "## Environment",
        "",
    ]

    # Device info
    serial = _sanitize_serial(data.serial_number, sanitize)
    lines.append(f"- **Serial Number**: `{serial}`")

    if data.firmware_version:
        lines.append(f"- **Firmware Version**: `{data.firmware_version}`")

    # Collection summary
    lines.extend(
        [
            "",
            "## Data Collection Summary",
            "",
        ]
    )

    for collection in data.collections:
        coll_serial = _sanitize_serial(collection.serial_number, sanitize)
        lines.extend(
            [
                f"### {collection.source.upper()} Collection",
                "",
                f"- **Serial**: `{coll_serial}`",
                f"- **Timestamp**: {collection.timestamp.strftime('%Y-%m-%d %H:%M:%S')}",
                f"- **Input Registers**: {collection.input_register_count()} "
                f"({collection.input_nonzero_count()} non-zero)",
                f"- **Holding Registers**: {collection.holding_register_count()} "
                f"({collection.holding_nonzero_count()} non-zero)",
            ]
        )

        if collection.errors:
            lines.append(f"- **Errors**: {len(collection.errors)}")
            for error in collection.errors[:3]:
                lines.append(f"  - `{error}`")
            if len(collection.errors) > 3:
                lines.append(f"  - _...and {len(collection.errors) - 3} more_")

        lines.append("")

    # Comparison summary
    if data.comparison:
        lines.extend(
            [
                "## Comparison Results",
                "",
                f"- **Status**: {'Match' if data.comparison.is_match() else 'Mismatches Found'}",
                f"- **Input Mismatches**: {len(data.comparison.input_mismatches)}",
                f"- **Holding Mismatches**: {len(data.comparison.holding_mismatches)}",
                "",
            ]
        )

        # Show first few mismatches
        if data.comparison.input_mismatches or data.comparison.holding_mismatches:
            lines.append("### Sample Mismatches")
            lines.append("")

            all_mismatches = (
                data.comparison.input_mismatches[:5] + data.comparison.holding_mismatches[:5]
            )
            if all_mismatches:
                lines.append("| Type | Address | Source A | Value A | Source B | Value B |")
                lines.append("|------|---------|----------|---------|----------|---------|")

                for m in data.comparison.input_mismatches[:3]:
                    lines.append(
                        f"| Input | {m.address} | {m.source_a} | {m.value_a} | "
                        f"{m.source_b} | {m.value_b} |"
                    )

                for m in data.comparison.holding_mismatches[:3]:
                    lines.append(
                        f"| Hold | {m.address} | {m.source_a} | {m.value_a} | "
                        f"{m.source_b} | {m.value_b} |"
                    )

                total = len(data.comparison.input_mismatches) + len(
                    data.comparison.holding_mismatches
                )
                if total > 6:
                    lines.append(f"\n_...and {total - 6} more mismatches (see attached files)_")

            lines.append("")

    # Instructions
    lines.extend(
        [
            "## Attached Files",
            "",
            "_Please attach the diagnostic ZIP file generated by the tool._",
            "",
            "The ZIP contains:",
            "- `modbus_diagnostic.json` - Structured data",
            "- `modbus_diagnostic.md` - Human-readable report",
            "- `modbus_diagnostic.csv` - Spreadsheet data",
            "- `modbus_diagnostic.bin` - Raw binary dump",
            "",
            "---",
            "_Generated by `pylxpweb-modbus-diag`_",
        ]
    )

    return "\n".join(lines)


def generate_gh_command(
    archive_path: Path | str,
    title: str | None = None,
    body: str | None = None,
    labels: list[str] | None = None,
    repo: str = "joyfulhouse/pylxpweb",
) -> str:
    """Generate `gh issue create` command.

    Args:
        archive_path: Path to diagnostic archive
        title: Issue title (optional, will prompt if None)
        body: Issue body (optional, will prompt if None)
        labels: Issue labels
        repo: GitHub repository (owner/repo)

    Returns:
        Shell command string
    """
    archive_path = Path(archive_path)

    # Build command parts
    parts = ["gh", "issue", "create"]

    # Repository
    parts.extend(["--repo", repo])

    # Title
    if title:
        parts.extend(["--title", title])

    # Body
    if body:
        # Write body to temp file for large content
        parts.extend(["--body", body])

    # Labels
    if labels:
        for label in labels:
            parts.extend(["--label", label])

    # Note about attachments
    # gh CLI doesn't support attachments directly, need to add manually
    cmd = shlex.join(parts)

    return cmd


def generate_full_instructions(
    archive_path: Path | str,
    data: DiagnosticData,
    sanitize: bool = True,
) -> str:
    """Generate complete instructions for creating GitHub issue.

    Args:
        archive_path: Path to diagnostic archive
        data: Diagnostic data
        sanitize: Whether to mask sensitive data

    Returns:
        Formatted instructions string
    """
    archive_path = Path(archive_path)
    serial = _sanitize_serial(data.serial_number, sanitize)

    # Suggested title
    title = f"Modbus register mapping issue - {serial}"

    # Generate issue body
    body = generate_issue_body(data, sanitize=sanitize)

    # Generate command
    cmd = generate_gh_command(
        archive_path=archive_path,
        title=title,
        labels=["bug", "modbus"],
        repo="joyfulhouse/pylxpweb",
    )

    instructions = f"""
================================================================================
                         GitHub Issue Creation
================================================================================

Option 1: Using GitHub CLI (gh)
-------------------------------

1. First, create the issue:

   {cmd}

2. After creating, edit the issue in your browser to attach the diagnostic file:
   {archive_path}

   (GitHub CLI doesn't support file attachments directly)


Option 2: Manual Creation
-------------------------

1. Go to: https://github.com/joyfulhouse/pylxpweb/issues/new

2. Title: {title}

3. Paste the issue body (copied below)

4. Attach the diagnostic file: {archive_path}

5. Add labels: bug, modbus


Issue Body (copy below this line):
================================================================================

{body}

================================================================================
"""

    return instructions


def _sanitize_serial(serial: str, sanitize: bool) -> str:
    """Mask serial number if sanitization is enabled."""
    return _sanitize_serial_impl(serial, enabled=sanitize)
