from flask import g, request
from typing import TypedDict

from src.lib.api import (
    create_api_v2_response,
    create_api_v2_client_error_response,
    TDAPIError,
    create_api_v2_not_found_error_response,
    create_api_v2_invalid_body_error_response,
    get_api_v2_request_data,
)
from src.lib.account import load_account
from src.lib.administrator import change_account_role
from src.types.account import Account, visible_roles, AccountRoleChange


def get_target_account_overview(account_id: str):
    parsed_account_id = int(account_id)

    if parsed_account_id == 0:
        return create_api_v2_client_error_response(
            TDAPIError(type="invalid_id", message="Account ID must be positive.")
        )

    target_account = load_account(account_id)

    if not target_account:
        return create_api_v2_not_found_error_response()

    response = create_api_v2_response(target_account)

    return response


class TDAccountUpdate(TypedDict):
    role: str


def change_target_account_details(account_id: str):
    parsed_account_id = int(account_id)
    body: TDAccountUpdate = get_api_v2_request_data(request)

    if parsed_account_id == 0:
        return create_api_v2_client_error_response(
            TDAPIError(type="invalid_id", message="Account ID must be positive.")
        )

    is_valid_body = body is not None and isinstance(body, dict) and (body.get("role") in visible_roles)

    if not is_valid_body:
        return create_api_v2_invalid_body_error_response()

    role = body["role"]
    target_account = load_account(account_id)

    if not target_account:
        return create_api_v2_not_found_error_response()

    if target_account.role == "administrator":
        return create_api_v2_client_error_response(
            TDAPIError(type="http_conflict", message="Cannot change the role of another admin."), 409
        )

    if target_account.role == role:
        return create_api_v2_client_error_response(
            TDAPIError(type="http_conflict", message="Target role is the same as old one."), 409
        )

    admin_account: Account = g.get("account")

    if admin_account.id == target_account.id:
        return create_api_v2_client_error_response(
            TDAPIError(type="http_conflict", message="Cannot change the role of yourself."), 409
        )

    change_data = AccountRoleChange(old_role=target_account.role, new_role=role)
    change_account_role([str(target_account.id)], change_data)

    response = create_api_v2_response(account_id)

    return response
