import base64
import json
import requests
import shutil
import os
from urllib.parse import unquote
import argparse

def download_base64_file(url):
    # Send GET request to fetch the base64 file content
    response = requests.get(url)
    if response.status_code == 200:
        return response.text
    else:
        print(f"Failed to download file. Status code: {response.status_code}")
        return None

def decode_base64_to_text(base64_str):
    # Decode the base64 string to raw bytes
    decoded_bytes = base64.b64decode(base64_str)
    # Convert the raw bytes to text (assuming it's UTF-8 encoded)
    return decoded_bytes.decode('utf-8')

def process_record(record):
    # Split the record by '@' and '?'
    user_info, params = record.split('?')
    password, server_info = user_info.split('@')
    _protocal, password = password.split('://')
    
    # Extract server and port
    server, port = server_info.split(":")
    
    # Extract URL params
    param_dict = {}
    for param in params.split('&'):
        key, value = param.split('=')
        param_dict[key] = value
    
    # Read the tag from the part after the '#'
    tag = unquote(record.split('#')[-1])[:-1]
    
    # Convert to JSON structure
    json_data = {
        "type": "trojan",
        "tag": tag,  # Decode the URL-encoded tag
        "server": server,
        "server_port": int(port),
        "password": password,
        "network": "tcp",
        "tls": {
            "enabled": True,
            "server_name": param_dict.get('sni', '').split('#')[0],
            "disable_sni": False,
            "insecure": param_dict.get('allowInsecure') == '1'
        }
    }
    
    return json_data, tag  # Return both JSON data and tag for selector

def convert_base64_to_json(url):
    base64_str = download_base64_file(url)
    if not base64_str:
        return [], []

    decoded_text = decode_base64_to_text(base64_str)
    
    # Process each line and convert to JSON
    records = decoded_text.strip().split('\n')
    json_records = []
    tags = []
    
    for record in records:
        json_data, tag = process_record(record)
        json_records.append(json_data)
        tags.append(tag)
    
    return json_records, tags

def create_selector(tags):
    # Create the selector object with all the tags from the base64 records
    return {
        "type": "selector",
        "tag": "crypto",
        "outbounds": tags,
        "default": tags[-1]
    }

def update_json_file(existing_json_file, new_json_data, selector_data, output_file):
    # Copy the original JSON file to a new location
    shutil.copy(existing_json_file, output_file)
    
    # Load the copied JSON file
    with open(output_file, 'r', encoding='utf-8') as f:
        data = json.load(f)
    
    # Append the new JSON data to the 'outbounds' field
    data['outbounds'].extend(new_json_data)
    # Append the selector to the 'outbounds' field
    data['outbounds'].append(selector_data)
    
    # Save the updated JSON back to the new file
    with open(output_file, 'w', encoding='utf-8') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    
    print(f"Updated {output_file} with new outbounds data.")

if __name__ == "__main__":
    # Argument parsing to allow overriding the URL and JSON file path
    parser = argparse.ArgumentParser(description="Process base64 and JSON")
    parser.add_argument("--url", type=str, default="https://hongxingdl.love/hxyunvip?token=99bb98fb84889a0c1e9792ea3145aae6", help="The URL to the base64 file")
    parser.add_argument("--json_file", type=str, default="philo-mobile.json", help="Path to the existing JSON file")
    parser.add_argument("--output", type=str, default="updated_json_file.json", help="Path to the new output JSON file")
    
    args = parser.parse_args()
    
    # Convert the base64 file to JSON and get the tags
    json_records, tags = convert_base64_to_json(args.url)
    
    # Create the selector data with the tags
    selector_data = create_selector(tags)

    # Update the JSON file with the new data, writing to a new file
    update_json_file(args.json_file, json_records, selector_data, args.output)
