#
#   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
import os
import socket
from functools import wraps

from flask import redirect, request, url_for
from werkzeug.wrappers import Response
from flask_login import current_user, logout_user
from jose import jwt

from ..auth.tokens import get_header_jwt_payload

from typing import Any, Callable, Dict, Optional, Tuple
JsonResponse = Tuple[str, int, Dict[str, str]]
OptionalJsonResponse = Optional[JsonResponse]

def is_admin(fn : Callable[..., Response]) -> Callable[..., Response]:
    @wraps(fn)
    def decorated_view(*args : Any, **kwargs : Any) -> Response:
        if current_user.role == "admin":
            return fn(*args, **kwargs)
        return redirect(url_for("login"))

    return decorated_view

def is_internal(fn : Callable[..., OptionalJsonResponse]) -> Callable[..., OptionalJsonResponse]:
    @wraps(fn)
    def decorated_view(*args : Any, **kwargs : Any) -> OptionalJsonResponse:
        remote_addr = (
            request.headers["X-Forwarded-For"].split(",")[0]
            if "X-Forwarded-For" in request.headers
            else request.remote_addr.split(",")[0]
        )
        ## Now only checks if it is wordpress container,
        ## but we should check if it is internal net and not haproxy
        if socket.gethostbyname("dd-apps-wordpress") == remote_addr:
            return fn(*args, **kwargs)
        return (
            json.dumps(
                {
                    "error": "unauthorized",
                    "msg": "Unauthorized access",
                }
            ),
            401,
            {"Content-Type": "application/json"},
        )

    return decorated_view


def has_token(fn : Callable[..., Any]) -> Callable[..., Any]:
    @wraps(fn)
    def decorated(*args : Any, **kwargs : Any) -> Any:
        payload = get_header_jwt_payload()
        return fn(*args, **kwargs)

    return decorated


def is_internal_or_has_token(fn : Callable[..., Any]) -> Callable[..., Any]:
    @wraps(fn)
    def decorated_view(*args : Any, **kwargs : Any) -> Any:
        remote_addr = (
            request.headers["X-Forwarded-For"].split(",")[0]
            if "X-Forwarded-For" in request.headers
            else request.remote_addr.split(",")[0]
        )
        payload = get_header_jwt_payload()

        if socket.gethostbyname("dd-apps-wordpress") == remote_addr:
            return fn(*args, **kwargs)
        payload = get_header_jwt_payload()
        return fn(*args, **kwargs)

    return decorated_view


def login_or_token(fn : Callable[..., Any]) -> Callable[..., Any]:
    @wraps(fn)
    def decorated_view(*args : Any, **kwargs : Any) -> Any:
        if current_user.is_authenticated:
            return fn(*args, **kwargs)
        payload = get_header_jwt_payload()
        return fn(*args, **kwargs)

    return decorated_view
