import disnake
import json
import os
import asyncio
from datetime import datetime
from typing import Optional, Dict, List
from src.logger import kuby_logger

class AdvancedLogger:
    def __init__(self, bot):
        self.bot = bot
        self.logs_dir = "data/logs"
        self.member_logs_dir = "data/member_logs"
        self.ensure_directories()
        
    def ensure_directories(self):
        """Ensure log directories exist"""
        os.makedirs(self.logs_dir, exist_ok=True)
        os.makedirs(self.member_logs_dir, exist_ok=True)
        
    def log_message_event(self, message: disnake.Message, event_type: str, details: Dict = None):
        """Log message events (sent, edited, deleted)"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "event_type": event_type,
            "message_id": message.id,
            "channel_id": message.channel.id,
            "channel_name": str(message.channel),
            "author_id": message.author.id,
            "author_name": str(message.author),
            "author_roles": [role.id for role in message.author.roles] if hasattr(message.author, 'roles') else [],
            "content": message.content,
            "attachments": [att.url for att in message.attachments],
            "embeds": [embed.to_dict() for embed in message.embeds],
            "details": details or {}
        }
        
        asyncio.create_task(self._write_log_async("messages", log_data))
        
    def log_role_event(self, member: disnake.Member, role: disnake.Role, event_type: str):
        """Log role changes (added/removed)"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "event_type": event_type,
            "member_id": member.id,
            "member_name": str(member),
            "role_id": role.id,
            "role_name": role.name,
            "role_color": str(role.color),
            "role_permissions": role.permissions.value
        }
        
        asyncio.create_task(self._write_log_async("roles", log_data))
        
    def log_voice_event(self, member: disnake.Member, channel: disnake.VoiceChannel, event_type: str):
        """Log voice channel events (join/leave)"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "event_type": event_type,
            "member_id": member.id,
            "member_name": str(member),
            "channel_id": channel.id,
            "channel_name": channel.name,
            "channel_type": str(channel.type)
        }
        
        asyncio.create_task(self._write_log_async("voice", log_data))
        
    def log_member_leave(self, member: disnake.Member):
        """Log when a member leaves the server"""
        roles_data = {
            "role_ids": [role.id for role in member.roles if role.name != "@everyone"],
            "role_names": [role.name for role in member.roles if role.name != "@everyone"],
            "permissions": [role.permissions.value for role in member.roles if role.name != "@everyone"]
        }
        
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "event_type": "member_leave",
            "member_id": member.id,
            "member_name": str(member),
            "member_discriminator": member.discriminator,
            "member_avatar": str(member.avatar.url) if member.avatar else None,
            "roles": roles_data,
            "joined_at": member.joined_at.isoformat() if member.joined_at else None
        }
        
        # Save to member-specific log
        asyncio.create_task(self._write_member_log_async(member.id, log_data))
        
        # Also save to general logs
        asyncio.create_task(self._write_log_async("member_events", log_data))
        
    def log_member_join(self, member: disnake.Member):
        """Log when a member joins the server"""
        log_data = {
            "timestamp": datetime.now().isoformat(),
            "event_type": "member_join",
            "member_id": member.id,
            "member_name": str(member),
            "member_discriminator": member.discriminator,
            "member_avatar": str(member.avatar.url) if member.avatar else None
        }
        
        asyncio.create_task(self._write_log_async("member_events", log_data))
        
    def check_previous_roles(self, member_id: int) -> Optional[Dict]:
        """Check if member has previous role data when rejoining"""
        member_log_file = f"{self.member_logs_dir}/{member_id}.json"

        if not os.path.exists(member_log_file):
            return None

        try:
            logs = []
            with open(member_log_file, 'r', encoding='utf-8') as f:
                content = f.read().strip()
                if not content:
                    return None

                # Handle legacy JSON list format
                if content.startswith('['):
                    try:
                        logs = json.loads(content)
                    except json.JSONDecodeError:
                        # File is corrupt or semi-corrupt, try line-by-line
                        pass

                # Try NDJSON line-by-line (handles both legacy and current format)
                lines = content.splitlines()
                for line in lines:
                    line = line.strip()
                    if not line:
                        continue
                    # Strip trailing/leading commas in case of semi-corrupt lines
                    line = line.strip(',')
                    if not line:
                        continue
                    try:
                        parsed = json.loads(line)
                        if isinstance(parsed, dict):
                            logs.append(parsed)
                    except json.JSONDecodeError:
                        continue  # Skip corrupt lines

                # Guard against empty logs list after parsing
                if not logs:
                    return None

            # Find the most recent leave event
            leave_events = [log for log in logs if isinstance(log, dict) and log.get("event_type") == "member_leave"]
            if leave_events:
                return leave_events[-1].get("roles", {})
                
        except Exception as e:
            kuby_logger.error(f"Error checking previous roles for {member_id}: {e}")
            
        return None

    async def _write_log_async(self, log_type: str, data: Dict):
        """Asynchronous wrapper for log writing"""
        return await asyncio.to_thread(self._write_log_sync, log_type, data)

    async def _write_member_log_async(self, member_id: int, data: Dict):
        """Asynchronous wrapper for member log writing"""
        return await asyncio.to_thread(self._write_member_log_sync, member_id, data)

    def _write_log_sync(self, log_type: str, data: Dict):
        """Write log data to appropriate file using NDJSON (Append-only)"""
        try:
            date_str = datetime.now().strftime("%Y-%m-%d")
            log_file = f"{self.logs_dir}/{log_type}_{date_str}.json"
            
            # Simple append in NDJSON format
            with open(log_file, 'a', encoding='utf-8') as f:
                f.write(json.dumps(data, ensure_ascii=False) + "\n")
                
        except Exception as e:
            # We don't use kuby_logger here to avoid infinite recursion if nested
            print(f"CRITICAL ERROR in AdvancedLogger._write_log_sync: {e}")
            
    def _write_member_log_sync(self, member_id: int, data: Dict):
        """Write member-specific log using NDJSON (Append-only)"""
        try:
            member_log_file = f"{self.member_logs_dir}/{member_id}.json"
            
            with open(member_log_file, 'a', encoding='utf-8') as f:
                f.write(json.dumps(data, ensure_ascii=False) + "\n")
                
        except Exception as e:
            print(f"CRITICAL ERROR in AdvancedLogger._write_member_log_sync: {e}")

    async def send_leave_notification(self, member: disnake.Member, channel: disnake.TextChannel):
        """Send notification when member leaves"""
        embed = disnake.Embed(
            title="👋 Membre parti",
            description=f"{member.mention} ({member.name}) a quitté le serveur.",
            color=disnake.Color.red(),
            timestamp=datetime.now()
        )
        
        embed.add_field(
            name="ID",
            value=str(member.id),
            inline=True
        )
        
        roles = [role for role in member.roles if role.name != "@everyone"]
        if roles:
            embed.add_field(
                name="Rôles",
                value=", ".join([role.mention for role in roles]),
                inline=False
            )
            
        embed.set_footer(text=f"ID: {member.id}")
        
        try:
            await channel.send(embed=embed)
            return True
        except Exception as e:
            kuby_logger.error(f"Error sending leave notification: {e}")
            return False
