"""Philips private tag query tool."""

import asyncio
import json
from pathlib import Path
from typing import Optional

import pydicom
from pydicom.errors import InvalidDicomError
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, _format_markdown_table
from dicom_mcp.helpers.philips import (
    _resolve_philips_private_tag,
    _list_philips_private_creators,
)


@mcp.tool(
    name="dicom_query_philips_private",
    annotations=ToolAnnotations(
        title="Query Philips Private Tags",
        readOnlyHint=True,
        destructiveHint=False,
        idempotentHint=True,
        openWorldHint=False,
    ),
)
async def dicom_query_philips_private(
    file_path: str,
    dd_number: Optional[int] = None,
    element_offset: Optional[int] = None,
    private_group: int = 0x2005,
    list_creators: bool = False,
    response_format: ResponseFormat = ResponseFormat.MARKDOWN,
) -> str:
    """Query Philips private DICOM tags using DD number and element offset.

    Philips MRI scanners store proprietary metadata in private tag blocks.
    Each block is reserved by a Private Creator tag containing a string
    like "Philips MR Imaging DD 001". Block assignments vary across
    scanners and software versions, so this tool resolves them dynamically.

    Usage modes:
      1. **List creators**: Set list_creators=True to see all Private Creator
         tags and their DD numbers. Use this to discover what's available.
      2. **Resolve a specific tag**: Provide dd_number and element_offset to
         look up a specific private element. For example, dd_number=1 with
         element_offset=0x85 finds shim calculation values.

    Common Philips DD numbers and offsets (group 2005):
      - DD 001, offset 0x85: Shim calculation values
      - DD 001, offset 0x63: Stack ID
      - DD 004, offset 0x00: MR Series data object

    Args:
        file_path: Path to a Philips DICOM file
        dd_number: The DD number to look up (e.g. 1 for "DD 001")
        element_offset: The element offset within the DD block (e.g. 0x85).
                       Can be provided as decimal (133) or will be interpreted
                       as decimal. Use hex notation in the description for clarity.
        private_group: The DICOM private group to search (default 0x2005)
        list_creators: If True, list all Private Creator tags instead of
                      resolving a specific tag
        response_format: Output format (markdown or json)
    """
    try:
        fp = Path(file_path)
        if not fp.exists():
            return f"Error: File not found: {file_path}"

        ds = await asyncio.to_thread(pydicom.dcmread, fp, stop_before_pixels=True)

        manufacturer = _safe_get_tag(ds, (0x0008, 0x0070))
        if "philips" not in manufacturer.lower():
            return (
                f"Warning: This file's manufacturer is '{manufacturer}', not Philips. "
                "Philips private tag resolution may not produce meaningful results."
            )

        if list_creators:
            # --- Mode 1: List all Private Creator tags ---
            creators = _list_philips_private_creators(ds, private_group)

            if not creators:
                return (
                    f"No Private Creator tags found in group "
                    f"({private_group:04X}) of {fp.name}"
                )

            if response_format == ResponseFormat.JSON:
                result = {
                    "file": fp.name,
                    "manufacturer": manufacturer,
                    "private_group": f"({private_group:04X})",
                    "creators": creators,
                }
                return json.dumps(result, indent=2)
            else:
                output = [
                    f"# Philips Private Creators: {fp.name}\n",
                    f"**Manufacturer**: {manufacturer}",
                    f"**Private group**: ({private_group:04X})",
                    f"**Creator slots found**: {len(creators)}\n",
                ]
                headers = ["Tag", "Block", "DD #", "Creator String"]
                rows = [
                    [
                        c["tag"],
                        c["block_byte"],
                        str(c["dd_number"]) if c["dd_number"] is not None else "N/A",
                        c["creator_string"],
                    ]
                    for c in creators
                ]
                output.append(_format_markdown_table(headers, rows))
                return "\n".join(output)

        elif dd_number is not None and element_offset is not None:
            # --- Mode 2: Resolve a specific private tag ---
            resolved_tag, creator_str, value_str = _resolve_philips_private_tag(
                ds, dd_number, element_offset, private_group
            )

            if resolved_tag is None:
                # Show available creators to help the user
                creators = _list_philips_private_creators(ds, private_group)
                available = ", ".join(
                    f"DD {c['dd_number']:03d}"
                    for c in creators
                    if c["dd_number"] is not None
                )
                return (
                    f"Error: No Private Creator found for DD {dd_number:03d} "
                    f"in group ({private_group:04X}) of {fp.name}.\n\n"
                    f"Available DD numbers: {available or 'none found'}"
                )

            tag_hex = f"({resolved_tag[0]:04X},{resolved_tag[1]:04X})"

            if response_format == ResponseFormat.JSON:
                result = {
                    "file": fp.name,
                    "manufacturer": manufacturer,
                    "query": {
                        "dd_number": dd_number,
                        "element_offset": f"0x{element_offset:02X}",
                        "private_group": f"({private_group:04X})",
                    },
                    "resolution": {
                        "creator_string": creator_str,
                        "resolved_tag": tag_hex,
                        "value": value_str,
                    },
                }
                return json.dumps(result, indent=2)
            else:
                output = [
                    f"# Philips Private Tag Lookup: {fp.name}\n",
                    f"**Manufacturer**: {manufacturer}\n",
                    "## Query",
                    f"- **DD number**: {dd_number:03d}",
                    f"- **Element offset**: 0x{element_offset:02X}",
                    f"- **Private group**: ({private_group:04X})\n",
                    "## Resolution",
                    f"- **Creator string**: {creator_str}",
                    f"- **Resolved tag**: {tag_hex}",
                    f"- **Value**: {value_str if value_str is not None else 'Tag exists but no value'}\n",
                ]
                return "\n".join(output)

        else:
            return (
                "Error: Provide either list_creators=True to discover available "
                "Private Creator tags, or both dd_number and element_offset to "
                "resolve a specific private tag."
            )

    except InvalidDicomError:
        return f"Error: Not a valid DICOM file: {file_path}"
    except Exception as e:
        return f"Error querying Philips private tags: {str(e)}"
