#!/usr/bin/env python
"""
Dropbox Token Setup Tool
-------------------------
Interactive CLI tool to generate an offline OAuth2 refresh token for Dropbox.
It automatically updates `dropbox_config.json` with the new refresh token.

Usage:
    python setup_dropbox_token.py
"""

import json
import os
import sys

try:
    import dropbox
    from dropbox.oauth import DropboxOAuth2FlowNoRedirect
except ImportError:
    print("[Error] The 'dropbox' library is required. Please run:")
    print("    pip install dropbox")
    sys.exit(1)


CONFIG_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "dropbox_config.json")


def load_config():
    if os.path.exists(CONFIG_FILE):
        try:
            with open(CONFIG_FILE, "r", encoding="utf-8") as f:
                return json.load(f)
        except Exception:
            pass
    return {}


def save_config(config_data):
    with open(CONFIG_FILE, "w", encoding="utf-8") as f:
        json.dump(config_data, f, indent=2, ensure_ascii=False)
    print(f"\n[Success] Updated '{CONFIG_FILE}' successfully!")


def main():
    print("=" * 60)
    print("         Dropbox OAuth2 Offline Token Generator")
    print("=" * 60)

    config = load_config()

    # Step 1: App Key
    app_key = config.get("app_key", "").strip()
    if not app_key:
        app_key = input("Enter Dropbox App Key: ").strip()
    else:
        print(f"Using App Key from config: {app_key}")
        change = input("Press ENTER to keep this key, or type a new one: ").strip()
        if change:
            app_key = change

    # Step 2: App Secret
    app_secret = config.get("app_secret", "").strip()
    if not app_secret:
        app_secret = input("Enter Dropbox App Secret: ").strip()
    else:
        print(f"Using App Secret from config: {app_secret[:4]}***")
        change = input("Press ENTER to keep this secret, or type a new one: ").strip()
        if change:
            app_secret = change

    if not app_key or not app_secret:
        print("[Error] Both App Key and App Secret are required.")
        sys.exit(1)

    # Initialize OAuth2 flow with offline access (needed for refresh token)
    auth_flow = DropboxOAuth2FlowNoRedirect(
        app_key, app_secret, token_access_type="offline"
    )

    authorize_url = auth_flow.start()
    print("\n" + "-" * 60)
    print("AUTHORIZATION STEPS:")
    print("1. Open the following URL in your web browser:\n")
    print(f"   {authorize_url}\n")
    print("2. Log in to Dropbox and click 'Allow'.")
    print("3. Copy the authorization code shown on screen.")
    print("-" * 60)

    auth_code = input("\nEnter the authorization code here: ").strip()

    if not auth_code:
        print("[Error] Authorization code cannot be empty.")
        sys.exit(1)

    print("\nExchanging authorization code for tokens...")
    try:
        oauth_result = auth_flow.finish(auth_code)
        access_token = oauth_result.access_token
        refresh_token = oauth_result.refresh_token

        print("\n[Success] Authorization succeeded!")
        print(f"Refresh Token: {refresh_token}")

        # Test the connection
        dbx = dropbox.Dropbox(
            oauth2_refresh_token=refresh_token,
            app_key=app_key,
            app_secret=app_secret,
        )
        account = dbx.users_get_current_account()
        print(f"Connected Account: {account.name.display_name} ({account.email})")

        # Save to json config
        config["app_key"] = app_key
        config["app_secret"] = app_secret
        config["refresh_token"] = refresh_token
        save_config(config)

        print("\nYou're all set! Dropbox is now configured.")

    except Exception as e:
        print(f"\n[Error] Failed to complete OAuth flow: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
