import re
from http.cookiejar import MozillaCookieJar

import vrchatapi
from vrchatapi.api import authentication_api
from vrchatapi.api import users_api
from vrchatapi.exceptions import UnauthorizedException
from vrchatapi.models.two_factor_auth_code import TwoFactorAuthCode
from vrchatapi.models.two_factor_email_code import TwoFactorEmailCode

from common.config_loader import getSecretValue

COOKIE_FILE = ".vrchat_cookie.txt"

USER_AGENT = (
    "VRC_OSC/1.0 "
    "(contact: test@gmail.com)"
)


def get_required_secret(section, key):
    value = getSecretValue(section, key)
    if not value:
        raise RuntimeError(f"{section}.{key} is not set in config/secrets.toml")
    return value


def setup_cookie_jar(api_client):
    cookie_jar = MozillaCookieJar(COOKIE_FILE)

    if os.path.exists(COOKIE_FILE):
        try:
            cookie_jar.load(
                ignore_discard=True,
                ignore_expires=True,
            )
        except Exception:
            pass

    api_client.rest_client.cookie_jar = cookie_jar
    return cookie_jar


def save_cookie_jar(cookie_jar):
    try:
        cookie_jar.save(
            ignore_discard=True,
            ignore_expires=True,
        )
    except Exception:
        pass


def login(api_client, cookie_jar):
    auth_api = authentication_api.AuthenticationApi(api_client)

    try:
        current_user = auth_api.get_current_user()
        save_cookie_jar(cookie_jar)
        return current_user

    except UnauthorizedException as e:
        reason = str(e.reason)

        if "Email 2 Factor Authentication" in reason:
            code = input("Email 2FA Code: ").strip()

            auth_api.verify2_fa_email_code(
                TwoFactorEmailCode(code)
            )

        elif "2 Factor Authentication" in reason:
            code = input("TOTP Code: ").strip()

            auth_api.verify2_fa(
                TwoFactorAuthCode(code)
            )

        else:
            raise

        current_user = auth_api.get_current_user()

        save_cookie_jar(cookie_jar)

        return current_user


def extract_user_id(text):
    match = re.search(
        r"(usr_[0-9a-fA-F\-]+)",
        text,
    )

    if not match:
        return None

    return match.group(1)


def main():
    text = input("参加者名: ").strip()

    user_id = extract_user_id(text)

    if not user_id:
        print(text)
        return

    configuration = vrchatapi.Configuration(
        username=get_required_secret("vrchat", "username"),
        password=get_required_secret("vrchat", "password"),
    )

    with vrchatapi.ApiClient(configuration) as api_client:
        api_client.user_agent = USER_AGENT

        api_client.default_headers["User-Agent"] = USER_AGENT

        cookie_jar = setup_cookie_jar(api_client)

        login(api_client, cookie_jar)

        users = users_api.UsersApi(api_client)

        user = users.get_user(user_id)

        print(user.display_name)

        save_cookie_jar(cookie_jar)


if __name__ == "__main__":
    main()
