import crypto from 'crypto';
import { closeTunnelIfUnused } from "./tunnel.manager";

interface RoomPermissions {
    canControl: boolean;
    canManageQueue: boolean;
}

interface RoomUser {
    id: string;
    username: string;
    avatar?: string;
    isHost: boolean;
    isGuest: boolean;
    userId?: number;
    permissions?: RoomPermissions;
    ipAddress?: string;
}

interface SourceContext {
    animeId: string;
    episode: string | number;
    source: string;
    extension: string;
    server: string;
    category: string;
}

export interface QueueItem {
    uid: string;
    metadata: RoomMetadata;
    videoData: any;
    addedBy: string;
}

interface RoomMetadata {
    id: string;
    title: string;
    episode: number;
    image?: string;
    source?: string;
    malId?: number;
}

interface RoomData {
    id: string;
    name: string;
    host: RoomUser;
    users: Map<string, RoomUser>;
    createdAt: number;
    currentVideo: {
        animeId?: number;
        episode?: number;
        source?: string;
        videoData?: any;
        currentTime: number;
        isPlaying: boolean;
        context?: SourceContext;
    } | null;
    password?: string;
    metadata?: RoomMetadata | null;
    exposed: boolean;
    publicUrl?: string;
    queue: QueueItem[];
    bannedIPs: Set<string>;
}

export const DEFAULT_GUEST_PERMISSIONS: RoomPermissions = {
    canControl: false,
    canManageQueue: false
};

const rooms = new Map<string, RoomData>();

export function generateRoomId(): string {
    return crypto.randomBytes(8).toString('hex');
}

export function createRoom(name: string, host: RoomUser, password?: string, exposed = false, publicUrl?: string): RoomData {
    const roomId = generateRoomId();

    const room: RoomData = {
        id: roomId,
        name,
        host,
        users: new Map([[host.id, host]]),
        createdAt: Date.now(),
        currentVideo: null,
        password: password || undefined,
        metadata: null,
        exposed,
        publicUrl,
        queue: [],
        bannedIPs: new Set()  // NUEVO
    };

    rooms.set(roomId, room);
    return room;
}

export function updateUserPermissions(roomId: string, userId: string, permissions: Partial<RoomPermissions>): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    const user: any = room.users.get(userId);
    if (!user) return false;

    if (user.isHost) return false;

    user.permissions = {
        ...user.permissions,
        ...permissions
    };

    return true;
}

export function banUserIP(roomId: string, ipAddress: string): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    room.bannedIPs.add(ipAddress);

    // Remover a todos los usuarios con esa IP
    Array.from(room.users.values()).forEach(user => {
        if (user.ipAddress === ipAddress) {
            removeUserFromRoom(roomId, user.id);
        }
    });

    return true;
}

export function unbanUserIP(roomId: string, ipAddress: string): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    return room.bannedIPs.delete(ipAddress);
}

export function isIPBanned(roomId: string, ipAddress: string): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;
    return room.bannedIPs.has(ipAddress);
}

export function getBannedIPs(roomId: string): string[] {
    const room = rooms.get(roomId);
    if (!room) return [];
    return Array.from(room.bannedIPs);
}

export function hasPermission(roomId: string, userId: string, permission: keyof RoomPermissions): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    const user = room.users.get(userId);
    if (!user) return false;

    // El host siempre tiene todos los permisos
    if (user.isHost) return true;

    // Si no tiene permisos definidos, usar defaults
    const userPerms = user.permissions || DEFAULT_GUEST_PERMISSIONS;
    return userPerms[permission] || false;
}

export function getRoom(roomId: string): RoomData | null {
    return rooms.get(roomId) || null;
}

export function getAllRooms(): RoomData[] {
    return Array.from(rooms.values()).map(room => ({
        ...room,
        users: room.users
    }));
}

export function addQueueItem(roomId: string, item: QueueItem): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;
    room.queue.push(item);
    return true;
}

export function removeQueueItem(roomId: string, itemUid: string): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;
    room.queue = room.queue.filter(i => i.uid !== itemUid);
    return true;
}

export function getNextQueueItem(roomId: string): QueueItem | undefined {
    const room = rooms.get(roomId);
    if (!room || room.queue.length === 0) return undefined;
    return room.queue.shift(); // Saca el primero y lo retorna
}

export function getAndRemoveQueueItem(roomId: string, itemUid: string): QueueItem | undefined {
    const room = rooms.get(roomId);
    if (!room) return undefined;

    const index = room.queue.findIndex(i => i.uid === itemUid);
    if (index === -1) return undefined;

    const [item] = room.queue.splice(index, 1);
    return item;
}

export function moveQueueItem(roomId: string, itemUid: string, direction: 'up' | 'down'): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    const index = room.queue.findIndex(i => i.uid === itemUid);
    if (index === -1) return false;

    const newIndex = direction === 'up' ? index - 1 : index + 1;

    if (newIndex < 0 || newIndex >= room.queue.length) return false;

    const temp = room.queue[newIndex];
    room.queue[newIndex] = room.queue[index];
    room.queue[index] = temp;

    return true;
}

export function addUserToRoom(roomId: string, user: RoomUser): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    room.users.set(user.id, user);
    return true;
}

export function removeUserFromRoom(roomId: string, userId: string): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    room.users.delete(userId);

    if (room.users.size === 0) {
        if (room.exposed) {
            closeTunnelIfUnused();
        }
        rooms.delete(roomId);
        return true;
    }

    if (room.host.id === userId && room.users.size > 0) {
        const newHost = Array.from(room.users.values())[0];
        newHost.isHost = true;
        room.host = newHost;
    }

    return true;
}

export function updateRoomVideo(roomId: string, videoData: any): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    room.currentVideo = {
        ...room.currentVideo,
        ...videoData
    };
    return true;
}

export function deleteRoom(roomId: string): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    if (room.exposed) {
        closeTunnelIfUnused();
    }

    return rooms.delete(roomId);
}

export function verifyRoomPassword(roomId: string, password?: string): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;
    if (!room.password) return true;
    if (!password) return false;

    return room.password === password;
}

export function updateRoomMetadata(roomId: string, metadata: any): boolean {
    const room = rooms.get(roomId);
    if (!room) return false;

    room.metadata = metadata;
    return true;
}