from __future__ import annotations

import secrets
from dataclasses import dataclass
from typing import Any, Dict, List, Literal, Optional, Union

from taskweaver.memory.type_vars import RoundState
from taskweaver.utils import create_id

from .post import Post


@dataclass
class Round:
    """A round is the basic unit of conversation in the project, which is a collection of posts.

    Args:
        id: the unique id of the round.
        post_list: a list of posts in the round.
        user_query: the query of the user.
        state: the state of the round.
    """

    id: str
    user_query: str
    state: RoundState
    post_list: List[Post]

    @staticmethod
    def create(
        user_query: str,
        id: Optional[Union[str, None]] = None,
        state: RoundState = "created",
        post_list: Optional[List[Post]] = None,
    ) -> Round:
        """Create a round with the given user query, id, and state."""
        return Round(
            id="round-" + create_id() if id is None else id,
            user_query=user_query,
            state=state,
            post_list=post_list if post_list is not None else [],
        )

    def __repr__(self):
        post_list_str = "\n".join([" " * 2 + str(item) for item in self.post_list])
        return "\n".join(
            [
                "Round:",
                f"- Query: {self.user_query}",
                f"- State: {self.state}",
                f"- Post Num:{len(self.post_list)}",
                f"- Post List: \n{post_list_str}\n\n",
            ],
        )

    def __str__(self):
        return self.__repr__()

    def to_dict(self) -> Dict[str, Any]:
        """Convert the round to a dict."""
        return {
            "id": self.id,
            "user_query": self.user_query,
            "state": self.state,
            "post_list": [post.to_dict() for post in self.post_list],
        }

    @staticmethod
    def from_dict(content: Dict[str, Any]) -> Round:
        """Convert the dict to a round. Will assign a new id to the round."""
        return Round(
            id="round-" + secrets.token_hex(6),
            user_query=content["user_query"],
            state=content["state"],
            post_list=[Post.from_dict(post) for post in content["post_list"]]
            if content["post_list"] is not None
            else [],
        )

    def add_post(self, post: Post):
        """Add a post to the post list."""
        self.post_list.append(post)

    def change_round_state(self, new_state: Literal["finished", "failed", "created"]):
        """Change the state of the round."""
        self.state = new_state
