"""
Datastore module for chat_arena.

This module provides utilities for storing the messages and the game results into database.
Currently, it supports Supabase.
"""
import json
import os
import uuid
from typing import List

from .arena import Arena
from .message import Message

# Attempt importing Supabase
try:
    import supabase

    # Get the Supabase URL and secret key from environment variables
    SUPABASE_URL = os.environ.get("SUPABASE_URL", "")
    SUPABASE_SECRET_KEY = os.environ.get("SUPABASE_SECRET_KEY", "")
    assert SUPABASE_URL and SUPABASE_SECRET_KEY
except Exception:
    supabase_available = False
else:
    supabase_available = True


# Store the messages into the Supabase database
class SupabaseDB:
    def __init__(self):
        assert supabase_available and SUPABASE_URL and SUPABASE_SECRET_KEY
        supabase_client = supabase.create_client(SUPABASE_URL, SUPABASE_SECRET_KEY)
        self.client = supabase_client

    # Save Arena state to Supabase
    def save_arena(self, arena: Arena):
        # Save the environment config
        self._save_environment(arena)

        # Save the player configs
        self._save_player_configs(arena)

        # Save the messages
        self.save_messages(arena)

    # Save the environment config of the arena
    def _save_environment(self, arena: Arena):
        env = arena.environment
        env_config = env.to_config()
        moderator_config = env_config.pop("moderator", None)

        arena_row = {
            "arena_id": str(arena.uuid),
            "global_prompt": arena.global_prompt,
            "env_type": env_config["env_type"],
            "env_config": json.dumps(env_config),
        }
        self.client.table("Arena").insert(arena_row).execute()

        # Get the moderator config
        if moderator_config:
            moderator_row = {
                "moderator_id": str(
                    uuid.uuid5(arena.uuid, json.dumps(moderator_config))
                ),
                "arena_id": str(arena.uuid),
                "role_desc": moderator_config["role_desc"],
                "terminal_condition": moderator_config["terminal_condition"],
                "backend_type": moderator_config["backend"]["backend_type"],
                "temperature": moderator_config["backend"]["temperature"],
                "max_tokens": moderator_config["backend"]["max_tokens"],
            }
            self.client.table("Moderator").insert(moderator_row).execute()

    # Save the player configs of the arena
    def _save_player_configs(self, arena: Arena):
        player_rows = []
        for player in arena.players:
            player_config = player.to_config()
            player_row = {
                "player_id": str(uuid.uuid5(arena.uuid, json.dumps(player_config))),
                "arena_id": str(arena.uuid),
                "name": player.name,
                "role_desc": player_config["role_desc"],
                "backend_type": player_config["backend"]["backend_type"],
                "temperature": player_config["backend"].get("temperature", None),
                "max_tokens": player_config["backend"].get("max_tokens", None),
            }
            player_rows.append(player_row)

        self.client.table("Player").insert(player_rows).execute()

    # Save the messages
    def save_messages(self, arena: Arena, messages: List[Message] = None):
        if messages is None:
            messages = arena.environment.get_observation()

        # Filter messages that are already logged
        messages = [msg for msg in messages if not msg.logged]

        message_rows = []
        for message in messages:
            message_row = {
                "message_id": str(uuid.uuid5(arena.uuid, message.msg_hash)),
                "arena_id": str(arena.uuid),
                "agent_name": message.agent_name,
                "content": message.content,
                "turn": message.turn,
                "timestamp": str(message.timestamp),
                "msg_type": message.msg_type,
                "visible_to": json.dumps(message.visible_to),
            }
            message_rows.append(message_row)

        self.client.table("Message").insert(message_rows).execute()

        # Mark the messages as logged
        for message in messages:
            message.logged = True


# Log the arena results into the Supabase database
def log_arena(arena: Arena, database=None):
    if database is None:
        pass
    else:
        database.save_arena(arena)


# Log the messages into the Supabase database
def log_messages(arena: Arena, messages: List[Message], database=None):
    if database is None:
        pass
    else:
        database.save_messages(arena, messages)
