"""
Moment Service - Extracts temporal narratives from resources.

Analyzes recent resources and sessions to identify temporal narratives
(meetings, coding sessions, conversations) and creates Moment entities
with temporal boundaries and metadata.
"""

import json
from datetime import datetime, timedelta
from typing import Any, Optional
from uuid import uuid4

from loguru import logger

from ...utils.schema_loader import load_agent_schema
from ...agentic.providers.pydantic_ai import create_agent
from ...agentic.serialization import serialize_agent_result
from ...models.entities.moment import Moment, Person
from ...models.entities.resource import Resource
from ...models.entities.message import Message
from ...services.postgres.repository import Repository
from ...services.postgres.service import PostgresService


async def construct_moments(
    user_id: str,
    db: PostgresService,
    default_model: str = "gpt-4o",
    lookback_hours: int = 24,
    limit: Optional[int] = None,
) -> dict[str, Any]:
    """
    Extract moments from resources.

    Analyzes recent resources to identify temporal narratives
    (meetings, coding sessions, conversations) and creates
    Moment entities with temporal boundaries and metadata.

    Process:
    1. Query PostgreSQL for recent resources and sessions for this user
    2. Load MomentBuilder agent schema from filesystem
    3. Run agent to extract moments from data
    4. Create Moment entities via Repository
    5. Link moments to source resources via graph edges
    6. Embeddings auto-generated by embedding worker

    Args:
        user_id: User to process
        db: Database service (already connected)
        default_model: LLM model for analysis (default: gpt-4o)
        lookback_hours: Hours to look back (default: 24)
        limit: Max resources to process

    Returns:
        Statistics about moment construction
    """
    cutoff = datetime.utcnow() - timedelta(hours=lookback_hours)

    # Create repositories
    resource_repo = Repository(Resource, "resources", db=db)
    message_repo = Repository(Message, "messages", db=db)
    moment_repo = Repository(Moment, "moments", db=db)

    # Query recent resources
    resources = await resource_repo.find(
        filters={
            "user_id": user_id,
        },
        order_by="created_at DESC",
        limit=limit,
    )

    # Filter by timestamp (SQL doesn't support comparisons in find yet)
    resources = [
        r for r in resources if r.created_at and r.created_at >= cutoff
    ]

    # Query recent messages (grouped by session_id for context)
    messages = await message_repo.find(
        filters={
            "user_id": user_id,
        },
        order_by="created_at DESC",
        limit=limit,
    )

    # Filter by timestamp
    messages = [m for m in messages if m.created_at >= cutoff]

    if not resources and not messages:
        return {
            "user_id": user_id,
            "lookback_hours": lookback_hours,
            "resources_queried": 0,
            "messages_queried": 0,
            "moments_created": 0,
            "graph_edges_added": 0,
            "status": "no_data",
        }

    # Load MomentBuilder agent schema
    agent_schema = load_agent_schema("moment-builder")

    # Prepare input data for agent
    input_data = {
        "resources": [
            {
                "id": str(r.id),
                "name": r.name,
                "category": r.category,
                "content": r.content,
                "created_at": (
                    r.created_at.isoformat() if r.created_at else None
                ),
            }
            for r in resources
        ],
        "messages": [
            {
                "id": str(m.id),
                "session_id": m.session_id,
                "message_type": m.message_type,
                "content": m.content,
                "created_at": m.created_at.isoformat(),
            }
            for m in messages
        ],
    }

    # Create and run MomentBuilder agent
    agent_runtime = await create_agent(
        agent_schema_override=agent_schema,
        model_override=default_model,  # type: ignore[arg-type]
    )

    result = await agent_runtime.run(json.dumps(input_data, indent=2))

    # Serialize result (critical for Pydantic models!)
    output_data = serialize_agent_result(result.output)

    # Type guard: ensure we have a dict
    if not isinstance(output_data, dict):
        raise ValueError(f"Expected dict from MomentBuilder agent, got {type(output_data)}")

    # Extract moments
    moments_data = output_data.get("moments", [])
    analysis_summary = output_data.get("analysis_summary", "")

    logger.info(
        f"MomentBuilder extracted {len(moments_data)} moments. Summary: {analysis_summary}"
    )

    # Create Moment entities
    created_moments = []
    total_edges = 0

    for moment_data in moments_data:
        # Map created_at/resource_ends_timestamp to starts_timestamp/ends_timestamp
        starts_ts_str = moment_data.get("created_at")
        ends_ts_str = moment_data.get("resource_ends_timestamp")

        if not starts_ts_str:
            logger.warning(f"Skipping moment without start timestamp: {moment_data.get('name')}")
            continue

        starts_ts = datetime.fromisoformat(starts_ts_str.replace("Z", "+00:00"))
        ends_ts = (
            datetime.fromisoformat(ends_ts_str.replace("Z", "+00:00"))
            if ends_ts_str
            else None
        )

        # Build graph edges to source resources
        source_resource_ids = moment_data.get("source_resource_ids", [])
        source_session_ids = moment_data.get("source_session_ids", [])

        graph_edges = []

        # Add edges to source resources
        for resource_id in source_resource_ids:
            graph_edges.append(
                {
                    "dst": resource_id,
                    "rel_type": "extracted_from",
                    "weight": 1.0,
                    "properties": {
                        "entity_type": "resource",
                        "extraction_method": "moment_builder_agent",
                    },
                    "created_at": datetime.utcnow().isoformat(),
                }
            )

        # Add edges to source sessions
        for session_id in source_session_ids:
            graph_edges.append(
                {
                    "dst": session_id,
                    "rel_type": "extracted_from",
                    "weight": 0.8,
                    "properties": {
                        "entity_type": "session",
                        "extraction_method": "moment_builder_agent",
                    },
                    "created_at": datetime.utcnow().isoformat(),
                }
            )

        # Create Moment entity
        moment = Moment(
            id=str(uuid4()),
            tenant_id=user_id,  # Set tenant_id = user_id
            user_id=user_id,
            name=moment_data.get("name"),
            moment_type=moment_data.get("moment_type"),
            category=moment_data.get("moment_type"),  # Use moment_type as category
            starts_timestamp=starts_ts,
            ends_timestamp=ends_ts,
            present_persons=[
                Person(id=p["id"], name=p["name"], role=p.get("comment"))
                for p in moment_data.get("present_persons", [])
            ],
            emotion_tags=moment_data.get("emotion_tags", []),
            topic_tags=moment_data.get("topic_tags", []),
            summary=moment_data.get("content"),  # Use content as summary
            source_resource_ids=source_resource_ids,
            graph_edges=graph_edges,
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow(),
        )

        # Save to database (embeddings auto-generated by embedding worker)
        await moment_repo.upsert(moment)
        created_moments.append(moment)
        total_edges += len(graph_edges)

        logger.debug(
            f"Created moment: {moment.name} ({moment.moment_type}) with {len(graph_edges)} edges"
        )

    return {
        "user_id": user_id,
        "lookback_hours": lookback_hours,
        "resources_queried": len(resources),
        "messages_queried": len(messages),
        "moments_created": len(created_moments),
        "graph_edges_added": total_edges,
        "analysis_summary": analysis_summary,
        "status": "success",
    }
