import json
from collections.abc import Mapping
from pathlib import Path

import mobase
from PyQt6.QtCore import QDateTime, QDir

from ..basic_features.basic_save_game_info import (
    BasicGameSaveGame,
    BasicGameSaveGameInfo,
    format_date,
)
from ..basic_game import BasicGame


class BaSSaveGame(BasicGameSaveGame):
    def __init__(self, filepath: Path):
        super().__init__(filepath)
        with open(self._filepath, "rb") as save:
            save_data = json.load(save)
        self._gameMode: str = save_data["gameModeId"]
        self._gender = (
            "Male" if save_data["creatureId"] == "PlayerDefaultMale" else "Female"
        )
        self._ethnicity: str = save_data["ethnicGroupId"]
        h, m, s = save_data["playTime"].split(":")
        self._elapsed = (int(h), int(m), float(s))
        f_stat = self._filepath.stat()
        self._created = f_stat.st_birthtime
        self._modified = f_stat.st_mtime

    def getName(self) -> str:
        return f"{self.getPlayerSlug()} - {self._gameMode}"

    def getCreationTime(self) -> QDateTime:
        return QDateTime.fromSecsSinceEpoch(int(self._created))

    def getModifiedTime(self) -> QDateTime:
        return QDateTime.fromSecsSinceEpoch(int(self._modified))

    def getPlayerSlug(self) -> str:
        return f"{self._gender} {self._ethnicity}"

    def getElapsed(self) -> str:
        return (
            f"{self._elapsed[0]} hours, "
            f"{self._elapsed[1]} minutes, "
            f"{int(self._elapsed[2])} seconds"
        )

    def getGameMode(self) -> str:
        return self._gameMode


def bas_parse_metadata(p: Path, save: mobase.ISaveGame) -> Mapping[str, str]:
    assert isinstance(save, BaSSaveGame)
    return {
        "Character": save.getPlayerSlug(),
        "Game Mode": save.getGameMode(),
        "Created At": format_date(save.getCreationTime()),
        "Last Saved": format_date(save.getModifiedTime()),
        "Session Duration": save.getElapsed(),
    }


class BaSGame(BasicGame):
    Name = "Blade & Sorcery Plugin"
    Author = "R3z Shark & Silarn"
    Version = "0.5.0"

    GameName = "Blade & Sorcery"
    GameShortName = "bladeandsorcery"
    GameBinary = "BladeAndSorcery.exe"
    GameDataPath = r"BladeAndSorcery_Data\\StreamingAssets\\Mods"
    GameDocumentsDirectory = "%DOCUMENTS%/My Games/BladeAndSorcery"
    GameSavesDirectory = "%GAME_DOCUMENTS%/Saves/Default"
    GameSaveExtension = "chr"
    GameSteamId = 629730
    GameSupportURL = (
        r"https://github.com/ModOrganizer2/modorganizer-basic_games/wiki/"
        "Game:-Blade-&-Sorcery"
    )

    def init(self, organizer: mobase.IOrganizer) -> bool:
        BasicGame.init(self, organizer)
        self._register_feature(
            BasicGameSaveGameInfo(get_metadata=bas_parse_metadata, max_width=400)
        )
        return True

    def listSaves(self, folder: QDir) -> list[mobase.ISaveGame]:
        ext = self._mappings.savegameExtension.get()
        return [
            BaSSaveGame(path) for path in Path(folder.absolutePath()).glob(f"*.{ext}")
        ]
