import json

from cli.infrastructure.formatting.fields import (
    format_cost,
    format_datetime,
    format_optional,
    format_tokens,
    format_uuid,
)
from cli.infrastructure.output import OutputFormat, OutputService
from cli.infrastructure.renderers.entity_renderer import FieldConfig
from alloy_runtime_types.dtos.content import ContentPartItemResponse
from alloy_runtime_types.dtos.templates import TagResponse


def present_content_part(response: ContentPartItemResponse) -> None:
    output = OutputService.get()

    if getattr(output, "format", OutputFormat.COMPACT) == OutputFormat.JSON:
        output.raw(response)
        return

    metadata_fields = [
        FieldConfig("id", "ID", str),
        FieldConfig(
            "message_id", "Message ID", lambda value: format_uuid(value, short=True)
        ),
        FieldConfig("message_role", "Message Role"),
        FieldConfig("part_index", "Part Index", str),
        FieldConfig("content_type_id", "Content Type"),
        FieldConfig(
            "content_structured",
            "Storage Type",
            lambda value: "structured" if value else "text",
        ),
        FieldConfig("created_at", "Created", format_datetime),
        FieldConfig("tags", "Tags", _format_tags),
    ]

    session = response.session
    if session is not None:
        metadata_fields.extend(
            [
                FieldConfig(
                    "id",
                    "Session ID",
                    lambda _: format_uuid(session.id, short=True),
                ),
                FieldConfig(
                    "id",
                    "Session Name",
                    lambda _: format_optional(
                        session.name,
                        placeholder="(unnamed session)",
                    ),
                ),
                FieldConfig(
                    "id",
                    "Session Activity",
                    lambda _: format_datetime(session.last_activity_at),
                ),
            ]
        )

    execution_metadata = response.execution_metadata
    if execution_metadata is not None:
        metadata_fields.extend(
            [
                FieldConfig(
                    "id",
                    "Execution ID",
                    lambda _: format_uuid(
                        execution_metadata.agent_execution_id, short=True
                    ),
                ),
                FieldConfig(
                    "id",
                    "Agent",
                    lambda _: format_optional(
                        execution_metadata.agent_name,
                        placeholder="(direct model call)",
                    ),
                ),
                FieldConfig(
                    "id",
                    "Provider",
                    lambda _: execution_metadata.provider_key,
                ),
                FieldConfig(
                    "id",
                    "Model",
                    lambda _: execution_metadata.provider_model_name,
                ),
                FieldConfig(
                    "id",
                    "Cost",
                    lambda _: format_optional(
                        execution_metadata.total_cost_usd,
                        formatter=format_cost,
                    ),
                ),
                FieldConfig(
                    "id",
                    "Tokens",
                    lambda _: format_optional(
                        execution_metadata.total_tokens,
                        formatter=format_tokens,
                    ),
                ),
                FieldConfig(
                    "id",
                    "Queued At",
                    lambda _: format_datetime(execution_metadata.queued_at),
                ),
            ]
        )

    output.entity(response, "Content Part", metadata_fields, raw_payload=response)

    content_fields = [
        FieldConfig("id", "Content", lambda _: _format_content(response)),
    ]
    output.entity(response, "Content Body", content_fields)


def _format_tags(tags: list[TagResponse]) -> str:
    if not tags:
        return "(no tags)"

    tag_paths = [t.tag_path for t in tags]
    return ", ".join(tag_paths)


def _format_content(response: ContentPartItemResponse) -> str:
    if response.content_text is not None:
        return response.content_text
    if response.content_structured is not None:
        return json.dumps(response.content_structured, indent=2, ensure_ascii=False)
    return "(no content)"
