#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import os
import re
import sys
import time
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)"
)

URLS = [
    "https://vrchat.com/home/user/usr_3a362bc1-0eb0-4c42-b6e9-c870b89a033c",
    "https://vrchat.com/home/user/usr_f7e6053b-c427-4a69-b906-c063cacbf7c5",
    "https://vrchat.com/home/user/usr_adf90786-449e-4608-a614-15b8525282c2",
    "https://vrchat.com/home/user/usr_b9affae3-8af4-4d77-b3d9-98d066117429",
    "https://vrchat.com/home/user/usr_212db5f1-f628-4d36-a19f-461ec35b591b",
    "https://vrchat.com/home/user/usr_013779d9-8746-4953-a1a5-d38735d4f72b",
    "https://vrchat.com/home/user/usr_bec2319d-b98f-4aaf-9591-9df0b8601d4e",
    "https://vrchat.com/home/user/usr_38b99395-1372-4bc5-8bed-f209b62279c3",
    "https://vrchat.com/home/user/usr_8da1c108-05fd-408b-b618-6a3a3145b9c8",
    "https://vrchat.com/home/user/usr_0d5eac85-a631-45e8-b5d7-ba9744299b83",
    "https://vrchat.com/home/user/usr_c20b2f2c-ea3c-4b4d-b1ac-1f2ee484c8e1",
    "https://vrchat.com/home/user/usr_6af54193-8930-46e5-97ea-548236e8e85d",
    "https://vrchat.com/home/user/usr_27078dc7-299c-4d6e-9de4-fcc0f80409d8",
    "https://vrchat.com/home/user/usr_6d0041b4-e242-43e9-999c-3d87c94eefb4",
    "https://vrchat.com/home/user/usr_4681fd97-ff3b-4b53-bed5-9beb5bc9e33b",
    "https://vrchat.com/home/user/usr_b53f3cf3-b0d8-4dde-9cb1-8669f1e26996",
    "https://vrchat.com/home/user/usr_18abe24e-4672-41e7-a8c4-b13629a49872",
    "https://vrchat.com/home/user/usr_113475ea-b9e4-4509-959f-0a19c0337be2",
    "https://vrchat.com/home/user/usr_af3871ad-4792-4702-b765-b474d53276b7",
    "https://vrchat.com/home/user/usr_82ac9b50-96a8-43ff-a105-26162341f82d",
]


def log(level, message):
    print(f"[{level}] {message}")


def wait_and_exit(code):
    input("Press Enter to exit...")
    sys.exit(code)


def get_required_secret(section, key):
    value = getSecretValue(section, key)

    if not value:
        raise RuntimeError(
            f"{section}.{key} is not set"
        )

    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 as e:
            log("ERROR", f"cookie load failed: {e}")

    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 as e:
        log("ERROR", f"cookie save failed: {e}")


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)

        log(
            "INFO",
            f"login ok: {current_user.display_name}"
        )

        return current_user

    except UnauthorizedException as e:

        reason = str(e.reason)

        if "Email 2 Factor Authentication" in reason:

            code = input(
                "[ACTION] Email 2FA Code: "
            ).strip()

            auth_api.verify2_fa_email_code(
                TwoFactorEmailCode(code)
            )

        elif "2 Factor Authentication" in reason:

            code = input(
                "[ACTION] TOTP Code: "
            ).strip()

            auth_api.verify2_fa(
                TwoFactorAuthCode(code)
            )

        else:
            raise

        current_user = auth_api.get_current_user()

        save_cookie_jar(cookie_jar)

        log(
            "INFO",
            f"login ok: {current_user.display_name}"
        )

        return current_user


def extract_user_id(url):

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

    if not match:
        return None

    return match.group(1)


def main():

    log("CHECK", "STEP=1 URL確認")

    user_ids = []

    for url in URLS:

        user_id = extract_user_id(url)

        if not user_id:
            log("ERROR", f"invalid url: {url}")
            continue

        user_ids.append(user_id)

    if not user_ids:
        log("FATAL", "user_id がありません")
        wait_and_exit(1)

    log("INFO", f"user_count={len(user_ids)}")

    log("CHECK", "STEP=2 ログイン")

    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)

        log(
            "CHECK",
            "STEP=3 displayName取得開始"
        )

        total = len(user_ids)

        for index, user_id in enumerate(
            user_ids,
            start=1,
        ):

            log(
                "CHECK",
                f"{index}/{total} {user_id}"
            )

            try:

                user = users.get_user(
                    user_id
                )

                print(
                    f"{user.display_name}"
                )

            except Exception as e:

                log(
                    "ERROR",
                    f"{user_id}: {e}"
                )

            time.sleep(10)

        save_cookie_jar(cookie_jar)

    log("CHECK", "STEP=4 結果確認")
    log("INFO", "完了")


if __name__ == "__main__":

    try:
        main()

    except KeyboardInterrupt:

        log(
            "INFO",
            "Ctrl+C detected"
        )

        log(
            "CHECK",
            "STEP=4 結果確認"
        )

        log(
            "INFO",
            "終了しました"
        )

    except Exception as e:

        log(
            "FATAL",
            str(e)
        )

        wait_and_exit(1)
