from typing import TypedDict, Literal

from flask import Blueprint, g, make_response, jsonify, abort, request

from src.lib.pagination import Pagination
from src.lib.administrator import get_accounts, change_account_role
from src.types.account import Account, visible_roles, AccountRoleChange

administrator_bp = Blueprint("api_administrator", __name__)


@administrator_bp.before_request
def check_credentials():
    account: Account = g.get("account")

    if account.role != "administrator":
        return abort(404)


class TDAccountsProps(TypedDict):
    accounts: list[Account]
    role_list: list[str]
    pagination: Pagination
    currentPage: Literal["admin"]


@administrator_bp.get("/administrator/accounts")
def get_accounts_list():
    queries = request.args.to_dict()
    queries["name"] = queries["name"] if queries.get("name") else None

    # transform `role` query into a list for db query
    if queries.get("role") and queries["role"] != "all":
        queries["role"] = [queries["role"]]
    else:
        queries["role"] = visible_roles

    pagination = Pagination(request)
    accounts = get_accounts(pagination, queries)
    props = TDAccountsProps(accounts=accounts, role_list=visible_roles, pagination=pagination, currentPage="admin")

    response = make_response(
        jsonify(props),
        200,
    )
    response.headers["Cache-Control"] = "s-maxage=60"

    return response


class TDAccountChangeBody(TypedDict):
    moderator: list[int]
    consumer: list[int]


class TDAccountRoleChangeProps(TypedDict):
    redirect: Literal["/account/administrator/accounts"]
    currentPage: Literal["admin"]


@administrator_bp.post("/administrator/accounts")
def change_account_roles():
    body: TDAccountChangeBody = request.get_json()
    # convert ids to `int`
    candidates = dict(
        moderator=[int(id) for id in body.get("moderator")] if body.get("moderator") else [],
        consumer=[int(id) for id in body.get("consumer")] if body.get("consumer") else [],
    )

    if candidates["moderator"]:
        change_account_role(
            candidates["moderator"],
            AccountRoleChange(
                old_role="consumer",
                new_role="moderator",
            ),
        )
    if candidates["consumer"]:
        change_account_role(
            candidates["consumer"],
            AccountRoleChange(
                old_role="moderator",
                new_role="consumer",
            ),
        )

    props = TDAccountRoleChangeProps(currentPage="admin", redirect="/account/administrator/accounts")

    response = make_response(jsonify(props), 200)
    response.headers["Cache-Control"] = "max-age=0, private, must-revalidate"

    return response
