#
#   Copyright © 2021,2022 IsardVDI S.L.
#   Copyright © 2022 Evilham <contact@evilham.com>
#
#   This file is part of DD
#
#   DD is free software: you can redistribute it and/or modify
#   it under the terms of the GNU Affero General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or (at your
#   option) any later version.
#
#   DD is distributed in the hope that it will be useful, but WITHOUT ANY
#   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
#   FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
#   details.
#
#   You should have received a copy of the GNU Affero General Public License
#   along with DD. If not, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: AGPL-3.0-or-later

import json
import logging as log
from operator import itemgetter
import os
import socket
import sys
import time
import traceback

from flask import request

from typing import TYPE_CHECKING, Any, Callable, Dict, Iterable, List
if TYPE_CHECKING:
    from admin.flaskapp import AdminFlaskApp

from admin.views.decorators import OptionalJsonResponse, is_internal



def setup_wp_views(app : "AdminFlaskApp") -> None:
    @app.json_route("/api/internal/users", methods=["GET"])
    @is_internal
    def internal_users() -> OptionalJsonResponse:
        log.error(socket.gethostbyname("dd-apps-wordpress"))
        if request.method == "GET":
            sorted_users = sorted(app.admin.get_mix_users(), key=itemgetter("username"))
            # group_users = [user for user in sorted_users if data['path'] in user['keycloak_groups']]
            users = []
            for user in sorted_users:
                if not user.get("enabled"):
                    continue
                users.append(user_parser(user))
            return json.dumps(users), 200, {"Content-Type": "application/json"}
        return None

    @app.json_route("/api/internal/users/filter", methods=["POST"])
    @is_internal
    def internal_users_search() -> OptionalJsonResponse:
        if request.method == "POST":
            data = request.get_json(force=True)
            users = app.admin.get_mix_users()
            result = [user_parser(user) for user in filter_users(users, data["text"])]
            sorted_result = sorted(result, key=itemgetter("id"))
            return json.dumps(sorted_result), 200, {"Content-Type": "application/json"}
        return None

    @app.json_route("/api/internal/groups", methods=["GET"])
    @is_internal
    def internal_groups() -> OptionalJsonResponse:
        if request.method == "GET":
            sorted_groups = sorted(app.admin.get_mix_groups(), key=itemgetter("name"))
            groups = []
            for group in sorted_groups:
                if not group["path"].startswith("/"):
                    continue
                groups.append(
                    {
                        "id": group["path"],
                        "name": group["name"],
                        "description": group.get("description", ""),
                    }
                )
            return json.dumps(groups), 200, {"Content-Type": "application/json"}
        return None

    @app.json_route("/api/internal/group/users", methods=["POST"])
    @is_internal
    def internal_group_users() -> OptionalJsonResponse:
        if request.method == "POST":
            data = request.get_json(force=True)
            sorted_users = sorted(app.admin.get_mix_users(), key=itemgetter("username"))
            # group_users = [user for user in sorted_users if data['path'] in user['keycloak_groups']]
            users = []
            for user in sorted_users:
                if data["path"] not in user["keycloak_groups"] or not user.get("enabled"):
                    continue
                users.append(user)
            if data.get("text", False) and data["text"] != "":
                result = [user_parser(user) for user in filter_users(users, data["text"])]
            else:
                result = [user_parser(user) for user in users]
            return json.dumps(result), 200, {"Content-Type": "application/json"}
        return None

    @app.json_route("/api/internal/roles", methods=["GET"])
    @is_internal
    def internal_roles() -> OptionalJsonResponse:
        if request.method == "GET":
            roles = []
            for role in sorted(app.admin.get_roles(), key=itemgetter("name")):
                if role["name"] == "admin":
                    continue
                roles.append(
                    {
                        "id": role["id"],
                        "name": role["name"],
                        "description": role.get("description", ""),
                    }
                )
            return json.dumps(roles), 200, {"Content-Type": "application/json"}
        return None

    @app.json_route("/api/internal/role/users", methods=["POST"])
    @is_internal
    def internal_role_users() -> OptionalJsonResponse:
        if request.method == "POST":
            data = request.get_json(force=True)
            sorted_users = sorted(app.admin.get_mix_users(), key=itemgetter("username"))
            # group_users = [user for user in sorted_users if data['path'] in user['keycloak_groups']]
            users = []
            for user in sorted_users:
                if data["role"] not in user["roles"] or not user.get("enabled"):
                    continue
                users.append(user)
            if data.get("text", False) and data["text"] != "":
                result = [user_parser(user) for user in filter_users(users, data["text"])]
            else:
                result = [user_parser(user) for user in users]
            return json.dumps(result), 200, {"Content-Type": "application/json"}
        return None

def user_parser(user : Dict[str, Any]) -> Dict[str, Any]:
    return {
        "id": user["username"],
        "first": user["first"],
        "last": user["last"],
        "role": user["roles"][0] if len(user["roles"]) else None,
        "email": user["email"],
        "groups": user["keycloak_groups"],
    }


def filter_users(users : Iterable[Dict[str, Any]], text : str) -> List[Dict[str, Any]]:
    return [
        user
        for user in users
        if text in user["username"]
        or text in user["first"]
        or text in user["last"]
        or text in user["email"]
    ]
