"""DICOM UID comparison tool."""

import asyncio
import json
from pathlib import Path
from mcp.types import ToolAnnotations

from dicom_mcp.server import mcp
from dicom_mcp.constants import ResponseFormat
from dicom_mcp.helpers.tags import _safe_get_tag, _resolve_tag
from dicom_mcp.helpers.files import _find_dicom_files


@mcp.tool(
    name="dicom_compare_uids",
    annotations=ToolAnnotations(
        title="Compare DICOM UIDs Between Directories",
        readOnlyHint=True,
        destructiveHint=False,
        idempotentHint=True,
        openWorldHint=False,
    ),
)
async def dicom_compare_uids(
    directory1: str,
    directory2: str,
    recursive: bool = True,
    compare_tag: str = "SeriesInstanceUID",
    response_format: ResponseFormat = ResponseFormat.MARKDOWN,
) -> str:
    """Compare UID sets between two DICOM directories.

    Extracts a specified UID tag from all files in both directories and
    performs set comparison to identify shared, missing, and extra UIDs.
    Useful for verifying that processed outputs contain all source series,
    or that two datasets are aligned.

    Args:
        directory1: First directory (the "reference" set)
        directory2: Second directory (the "comparison" set)
        recursive: Search subdirectories (default True)
        compare_tag: DICOM tag keyword or hex code to compare
                     (default "SeriesInstanceUID"). Supports keywords
                     like "StudyInstanceUID" or hex codes like "0020,000E".
        response_format: Output format (markdown or json)
    """
    try:
        dir1 = Path(directory1)
        dir2 = Path(directory2)

        if not dir1.exists():
            return f"Error: Directory not found: {directory1}"
        if not dir2.exists():
            return f"Error: Directory not found: {directory2}"

        # Resolve the tag specification
        tag_tuple, tag_name = _resolve_tag(compare_tag)
        if tag_tuple is None:
            return (
                f"Error: Could not resolve tag '{compare_tag}'. "
                "Use a keyword like 'SeriesInstanceUID' or hex code like '0020,000E'."
            )

        # Read files from both directories
        files1, truncated1 = await asyncio.to_thread(_find_dicom_files, dir1, recursive)
        files2, truncated2 = await asyncio.to_thread(_find_dicom_files, dir2, recursive)

        if not files1:
            return f"No DICOM files found in {directory1}"
        if not files2:
            return f"No DICOM files found in {directory2}"

        # Extract UIDs from each directory
        uids1 = set()
        for _, ds in files1:
            val = _safe_get_tag(ds, tag_tuple)
            if val != "N/A":
                uids1.add(str(val))

        uids2 = set()
        for _, ds in files2:
            val = _safe_get_tag(ds, tag_tuple)
            if val != "N/A":
                uids2.add(str(val))

        # Set comparison
        shared = sorted(uids1 & uids2)
        only_in_first = sorted(uids1 - uids2)
        only_in_second = sorted(uids2 - uids1)
        match = len(only_in_first) == 0 and len(only_in_second) == 0

        result = {
            "compare_tag": tag_name,
            "directory1": str(dir1),
            "directory2": str(dir2),
            "directory1_files": len(files1),
            "directory2_files": len(files2),
            "directory1_truncated": truncated1,
            "directory2_truncated": truncated2,
            "unique_in_directory1": len(uids1),
            "unique_in_directory2": len(uids2),
            "shared": len(shared),
            "only_in_directory1": len(only_in_first),
            "only_in_directory2": len(only_in_second),
            "match": match,
            "shared_values": shared,
            "only_in_directory1_values": only_in_first,
            "only_in_directory2_values": only_in_second,
        }

        if response_format == ResponseFormat.JSON:
            return json.dumps(result, indent=2)
        else:
            status = "MATCH" if match else "MISMATCH"
            output = [
                f"# UID Comparison: {tag_name}\n",
                f"**Status**: {status}\n",
                "## Summary\n",
                "| | Directory 1 | Directory 2 |",
                "|--|------------|------------|",
                f"| **Path** | {dir1.name} | {dir2.name} |",
                f"| **Files scanned** | {len(files1)} | {len(files2)} |",
                f"| **Unique {tag_name}s** | {len(uids1)} | {len(uids2)} |",
                "",
                f"- **Shared**: {len(shared)}",
                f"- **Only in directory 1**: {len(only_in_first)}",
                f"- **Only in directory 2**: {len(only_in_second)}",
            ]

            if truncated1 or truncated2:
                output.append(
                    "\n**Warning**: File scan was truncated in one or both "
                    "directories. Results may be incomplete."
                )

            if only_in_first:
                output.append(f"\n## Only in {dir1.name}\n")
                for uid in only_in_first:
                    output.append(f"- `{uid}`")

            if only_in_second:
                output.append(f"\n## Only in {dir2.name}\n")
                for uid in only_in_second:
                    output.append(f"- `{uid}`")

            return "\n".join(output)

    except Exception as e:
        return f"Error comparing UIDs: {str(e)}"
