from nicegui import ui
import db
import auth as auth_module
import layout


@ui.page("/dept/members")
async def dept_members_page():
    await auth_module.sync_session()
    if not auth_module.is_authenticated():
        ui.navigate.to("/login")
        return

    user = auth_module.current_user()
    user_id = user["id"]

    # All departments the user belongs to, with their role
    all_depts = await db.fetch(
        """
        SELECT d.id, d.name, i.name AS organization_name, ud.role
        FROM user_department ud
        JOIN department d ON d.id = ud.department_id
        JOIN organization  i ON i.id = d.organization_id
        WHERE ud.user_id = $1::uuid
        ORDER BY i.name, d.name
        """,
        user_id,
    )

    # All users available to assign (only needed for admin depts)
    all_users = await db.fetch(
        "SELECT id, name, email FROM user_account ORDER BY name",
    )

    with layout.page("My Departments"):
        if not all_depts:
            ui.label("You are not a member of any department.").classes(
                "text-gray-500 italic"
            )
            return

        for dept in all_depts:
            dept_id = str(dept["id"])
            dept_name = f"{dept['organization_name']} / {dept['name']}"
            is_admin = dept["role"] == "admin"

            icon = "admin_panel_settings" if is_admin else "folder_open"
            with (
                ui.expansion(dept_name, icon=icon)
                .classes("w-full border rounded-lg")
                .props("default-opened")
            ):
                members_col = ui.column().classes("w-full gap-1 px-2")

                async def refresh(did=dept_id, col=members_col):
                    col.clear()
                    members = await db.fetch(
                        """
                        SELECT ud.user_id, ua.name, ua.email, ud.role
                        FROM user_department ud
                        JOIN user_account ua ON ua.id = ud.user_id
                        WHERE ud.department_id = $1::uuid
                        ORDER BY ua.name
                        """,
                        did,
                    )
                    with col:
                        if not members:
                            ui.label("No members yet.").classes(
                                "text-sm text-gray-400 italic"
                            )
                        for m in members:
                            with ui.row().classes(
                                "w-full items-center justify-between py-1"
                            ):
                                ui.label(f"{m['name']} ({m['email']})").classes(
                                    "text-sm"
                                )
                                ui.badge(m["role"]).props("color=primary")
                                if is_admin:
                                    ui.button(icon="close").props(
                                        "flat round dense color=negative"
                                    ).on(
                                        "click",
                                        handler=lambda _, uid=str(m["user_id"]), d=did, c=col: (
                                            _revoke(uid, d, c)
                                        ),
                                    )

                await refresh(dept_id, members_col)

                if is_admin:
                    ui.separator().classes("my-2")
                    user_options = {
                        str(u["id"]): f"{u['name']} ({u['email']})" for u in all_users
                    }
                    with ui.row().classes("w-full items-end gap-2 px-2 pb-2"):
                        user_select = ui.select(user_options, label="User").classes(
                            "flex-1"
                        )
                        role_select = ui.select(
                            {"member": "Member", "admin": "Admin"},
                            label="Role",
                            value="member",
                        ).classes("w-32")
                        error = ui.label("").classes("text-red-500 text-sm")

                        async def add(
                            did=dept_id,
                            col=members_col,
                            us=user_select,
                            rs=role_select,
                            err=error,
                        ):
                            err.text = ""
                            if not us.value:
                                err.text = "Select a user."
                                return
                            try:
                                # Organisational tracking
                                await db.execute(
                                    """
                                    INSERT INTO user_department (user_id, department_id, role)
                                    VALUES ($1::uuid, $2::uuid, $3)
                                    ON CONFLICT (user_id, department_id) DO UPDATE SET role = EXCLUDED.role
                                    """,
                                    us.value,
                                    did,
                                    rs.value,
                                )
                                # Full-scope access management entry (entity=NULL, time=NULL = no restrictions)
                                dept_info = await db.fetchrow(
                                    "SELECT d.name, d.organization_id FROM department d WHERE d.id = $1::uuid",
                                    did,
                                )
                                management_id = await db.fetchval(
                                    """
                                    INSERT INTO management (organization_id, department_id, name)
                                    VALUES ($1::uuid, $2::uuid, $3)
                                    RETURNING id
                                    """,
                                    str(dept_info["organization_id"]),
                                    did,
                                    dept_info["name"],
                                )
                                await db.execute(
                                    """
                                    INSERT INTO user_management (user_id, management_id, role)
                                    VALUES ($1::uuid, $2::uuid, $3)
                                    ON CONFLICT (user_id, management_id) DO NOTHING
                                    """,
                                    us.value,
                                    str(management_id),
                                    rs.value,
                                )
                                us.value = None
                                await refresh(did, col)
                            except Exception as e:
                                err.text = f"Error: {e}"

                        ui.button("Add", icon="add", on_click=add).props(
                            "color=primary"
                        )


async def _revoke(user_id: str, dept_id: str, col) -> None:
    # Remove organisational tracking entry
    await db.execute(
        "DELETE FROM user_department WHERE user_id = $1::uuid AND department_id = $2::uuid",
        user_id,
        dept_id,
    )
    # Remove the corresponding full-scope access management entry (entity=NULL, time=NULL)
    await db.execute(
        """
        DELETE FROM user_management
        WHERE user_id = $1::uuid
          AND management_id IN (
              SELECT p.id FROM management p
              WHERE p.department_id = $2::uuid
                AND p.entity       IS NULL
                AND p.time_start   IS NULL
                AND p.time_end     IS NULL
          )
        """,
        user_id,
        dept_id,
    )
    ui.navigate.to("/dept/members")
