"""
FreeExile Guild Roster Service: Guild Membership & Presence Integration.
Joins guild membership with real-time player presence for R3 Safe Teleportation targeting.
"""

from __future__ import annotations
from typing import Any, Dict, List, Optional, Union
from server.social.social_types import (
    GuildMemberPresenceDTO,
    PresenceStatus,
    RESTRICTED_PRIVATE_ZONES,
)

try:
    from server.trade.guild_stash_service import GuildMember, GuildRole
except ImportError:
    GuildMember = None  # type: ignore
    GuildRole = None  # type: ignore


class GuildRosterService:
    """Service providing lightweight guild membership roster joined with live presence."""

    def __init__(self, social_service: Optional[Any] = None) -> None:
        self.guilds: Dict[str, List[Any]] = {}
        self._social_service = social_service

    def register_member(self, guild_id: str, member: Union[GuildMemberPresenceDTO, Any]) -> None:
        """Registers a member in the given guild roster."""
        self.guilds.setdefault(guild_id, []).append(member)

    def register_guild_member(self, guild_id: str, member: Any) -> None:
        """Alias for register_member supporting server/trade/guild_stash_service.GuildMember."""
        self.register_member(guild_id, member)

    def get_guild_roster_with_presence(self, guild_id: str) -> List[GuildMemberPresenceDTO]:
        """
        Retrieves guild members joined with real-time presence.
        Calculates teleport targetability: True if online and not in restricted private zone.
        """
        members = self.guilds.get(guild_id)
        if not members:
            return []

        roster: List[GuildMemberPresenceDTO] = []
        for m in members:
            dto = self._resolve_member_presence(m)
            roster.append(dto)
        return roster

    def _resolve_member_presence(self, m: Any) -> GuildMemberPresenceDTO:
        """Resolves presence metadata and teleport targetability for a guild member."""
        if isinstance(m, GuildMemberPresenceDTO):
            # Check if live presence cache has fresher info
            if self._social_service is not None and hasattr(self._social_service, "_presence_cache"):
                cached = self._social_service._presence_cache.get(m.player_id)
                if cached:
                    is_online = cached.presence_status != PresenceStatus.OFFLINE
                    targetable = (
                        is_online
                        and bool(cached.zone_id)
                        and cached.zone_id not in RESTRICTED_PRIVATE_ZONES
                        and not cached.zone_id.startswith("secret_")
                        and not cached.zone_id.startswith("zone_secret")
                    )
                    return GuildMemberPresenceDTO(
                        player_id=m.player_id,
                        character_name=cached.character_name or m.character_name,
                        role=m.role,
                        level=cached.level,
                        presence_status=cached.presence_status,
                        zone_id=cached.zone_id,
                        is_teleport_targetable=targetable,
                    )
            return m

        # Handles server.trade.guild_stash_service.GuildMember or generic member objects
        player_id = getattr(m, "player_id", "")
        player_name = getattr(m, "player_name", getattr(m, "name", player_id))
        raw_role = getattr(m, "role", "Huynh Đệ")

        role_str = "Huynh Đệ"
        if hasattr(raw_role, "value"):
            val = str(raw_role.value)
            if val == "GUILD_MASTER":
                role_str = "Đầu Lĩnh"
            elif val == "OFFICER":
                role_str = "Trưởng Lão"
        elif isinstance(raw_role, str):
            role_str = raw_role

        level = 1
        status = PresenceStatus.OFFLINE
        zone_id = ""

        if self._social_service is not None and hasattr(self._social_service, "_presence_cache"):
            cached = self._social_service._presence_cache.get(player_id)
            if cached:
                level = cached.level
                status = cached.presence_status
                zone_id = cached.zone_id

        is_online = status != PresenceStatus.OFFLINE
        targetable = (
            is_online
            and bool(zone_id)
            and zone_id not in RESTRICTED_PRIVATE_ZONES
            and not zone_id.startswith("secret_")
            and not zone_id.startswith("zone_secret")
        )

        return GuildMemberPresenceDTO(
            player_id=player_id,
            character_name=player_name,
            role=role_str,
            level=level,
            presence_status=status,
            zone_id=zone_id,
            is_teleport_targetable=targetable,
        )
