import re
import secrets
import string

from database import execute, fetch_one, fetch_all

DEFAULT_ROLE = "member"


def validate_invite_code(invite_code: str):
    if not 6 <= len(invite_code) <= 32:
        return False

    if not re.fullmatch(r"[A-Za-z0-9]+", invite_code):
        return False

    return True


def create_room(user_id: int, room_name: str, invite_code: str):

    if not validate_invite_code(invite_code):
        return {
            "status": "failed",
            "reason": "invalid_invite_code",
        }

    room_id = execute(
        """
        INSERT INTO rooms (name, owner_id, invite_code)
        VALUES (?, ?, ?)
        """,
        (
            room_name,
            user_id,
            invite_code,
        )
    )

    member_id = execute(
        """
        INSERT INTO room_members (room_id, user_id, role)
        VALUES (?, ?, ?)
        """,
        (
            room_id,
            user_id,
            "owner",
        )
    )

    return {
        "room_id": room_id,
        "member_id": member_id,
    }


def search_room(invite_code: str):

    room = fetch_one(
        """
        SELECT name
        FROM rooms
        WHERE invite_code = ?
        """,
        (invite_code,)
    )

    if room is None:
        return None

    return room["name"]


def accept_room(user_id: int, invite_code: str):

    room = fetch_one(
        """
        SELECT id
        FROM rooms
        WHERE invite_code = ?
        """,
        (invite_code,)
    )

    if room is None:
        return None

    room_id = room["id"]

    existing = fetch_one(
        """
        SELECT *
        FROM room_members
        WHERE room_id = ?
        AND user_id = ?
        """,
        (
            room_id,
            user_id,
        )
    )

    if existing:
        return None

    member_id = execute(
        """
        INSERT INTO room_members
        (room_id, user_id, role)
        VALUES (?, ?, ?)
        """,
        (
            room_id,
            user_id,
            DEFAULT_ROLE,
        )
    )

    return {
        "room_id": room_id,
        "member_id": member_id,
    }


def get_rooms(user_id: int):

    return fetch_all(
        """
        SELECT
            rooms.id,
            rooms.name,
            rooms.owner_id,
            rooms.invite_code,
            room_members.role
        FROM rooms
        JOIN room_members
            ON rooms.id = room_members.room_id
        WHERE room_members.user_id = ?
        """,
        (user_id,)
    )


def delete_room(room_id: int):

    room = fetch_one(
        """
        SELECT id
        FROM rooms
        WHERE id = ?
        """,
        (room_id,)
    )

    if not room:
        return {"error": "room not found"}

    execute(
        """
        DELETE FROM rooms
        WHERE id = ?
        """,
        (room_id,)
    )

    return {"status": "deleted"}


def get_room(room_id: int, user_id: int):

    room = fetch_one(
        """
        SELECT
            rooms.id,
            rooms.name,
            rooms.owner_id,
            room_members.role
        FROM rooms
        JOIN room_members
            ON rooms.id = room_members.room_id
        WHERE rooms.id = ?
        AND room_members.user_id = ?
        """,
        (
            room_id,
            user_id,
        )
    )

    if room is None:
        return None

    members = fetch_all(
        """
        SELECT
            users.id,
            users.username,
            room_members.role
        FROM room_members
        JOIN users
            ON users.id = room_members.user_id
        WHERE room_members.room_id = ?
        """,
        (room_id,)
    )

    events = fetch_all(
        """
        SELECT *
        FROM events
        WHERE room_id = ?
        ORDER BY start_time
        """,
        (room_id,)
    )

    return {
        "room": dict(room),
        "members": [dict(member) for member in members],
        "events": [dict(event) for event in events],
    }


def get_room_members(room_id: int):

    return fetch_all(
        """
        SELECT
            users.id,
            users.username,
            room_members.role
        FROM room_members
        JOIN users
            ON users.id = room_members.user_id
        WHERE room_members.room_id = ?
        """,
        (room_id,)
    )


def leave_room(room_id: int, user_id: int):

    execute(
        """
        DELETE FROM room_members
        WHERE room_id = ?
        AND user_id = ?
        """,
        (
            room_id,
            user_id,
        )
    )


def change_room_name(room_id: int, new_name: str, user_id: int):

    room = fetch_one(
        """
        SELECT id
        FROM rooms
        WHERE id = ?
        """,
        (room_id,)
    )

    if not room:
        return {
            "status": "error",
            "reason": "room_not_found",
        }

    execute(
        """
        UPDATE rooms
        SET name = ?
        WHERE id = ?
        """,
        (
            new_name,
            room_id,
        )
    )

    return {
        "status": "updated",
        "new_name": new_name,
        "room_id": room_id,
        "updated_by": user_id,
    }


def regenerate_invite_code(room_id: int):

    new_code = ''.join(
        secrets.choice(string.ascii_uppercase + string.digits)
        for _ in range(8)
    )

    execute(
        """
        UPDATE rooms
        SET invite_code = ?
        WHERE id = ?
        """,
        (
            new_code,
            room_id,
        )
    )

    return {
        "status": "updated",
        "room_id": room_id,
        "invite_code": new_code,
    }


def remove_room_member(room_id: int, user_id: int):

    member = fetch_one(
        """
        SELECT 1
        FROM room_members
        WHERE room_id = ?
        AND user_id = ?
        """,
        (
            room_id,
            user_id,
        )
    )

    if member is None:
        return False

    execute(
        """
        DELETE FROM room_members
        WHERE room_id = ?
        AND user_id = ?
        """,
        (
            room_id,
            user_id,
        )
    )

    return True


def update_member_role(room_id: int, user_id: int, role: str):

    execute(
        """
        UPDATE room_members
        SET role = ?
        WHERE room_id = ?
        AND user_id = ?
        """,
        (
            role,
            room_id,
            user_id,
        )
    )