import sys
import threading
import time

# ANSI Color Codes
RESET = "\033[0m"
BOLD = "\033[1m"
GREEN = "\033[32m"
CYAN = "\033[36m"
YELLOW = "\033[33m"
RED = "\033[31m"
GRAY = "\033[90m"

def print_header():
    print(f"\n{BOLD}▲ AppForge{RESET}\n")

def print_footer():
    print(f"\n{GRAY}AppForge CLI")
    print(f"Built by AppForge Team [Maintainer - JuniorSir]{RESET}\n")

def print_success(msg):
    print(f"{GREEN}✔{RESET} {msg}")

def print_info(msg):
    print(f"{CYAN}?{RESET} {msg}")

def print_warning(msg):
    print(f"{YELLOW}⚠{RESET} {msg}")

def print_error(msg):
    print(f"{RED}✖{RESET} {msg}")
    sys.exit(1)

def prompt(question, default=""):
    prompt_text = f"{CYAN}?{RESET} {question}"
    if default:
        prompt_text += f" {GRAY}({default}){RESET}"
    prompt_text += ": "
    
    try:
        response = input(prompt_text).strip()
        return response if response else default
    except KeyboardInterrupt:
        print_error("\nOperation cancelled.")

# --- NEW TYPEWRITER & SPINNER ANIMATION ---

def _spinner_animation(stop_event, message):
    """Letter-by-letter typing followed by spinner."""
    
    displayed_text = ""

    # Phase 1: Letter typewriter
    for char in message:
        if stop_event.is_set():
            break

        displayed_text += char
        sys.stdout.write(f"\r{CYAN}●{RESET} {displayed_text}")
        sys.stdout.flush()
        time.sleep(0.03)   # typing speed

    # Phase 2: Spinner
    spinner_chars = "|/-\\"
    idx = 0

    while not stop_event.is_set():
        char = spinner_chars[idx % len(spinner_chars)]

        sys.stdout.write(f"\r{CYAN}{char}{RESET} {displayed_text}")
        sys.stdout.flush()

        idx += 1
        time.sleep(0.1)

def run_with_spinner(target_func, message):
    stop_event = threading.Event()
    spinner_thread = threading.Thread(target=_spinner_animation, args=(stop_event, message))
    
    spinner_thread.start()
    
    try:
        result = target_func()
    except Exception as e:
        stop_event.set()
        spinner_thread.join()
        # Clean failure output
        sys.stdout.write(f"\r{RED}✖{RESET} {message.strip()} {GRAY}failed!{RESET}       \n")
        print_error(f"Error: {e}")
        return None

    stop_event.set()
    spinner_thread.join()
    
    # Clean success output with PERFECT spacing
    # The trailing spaces ensure any leftover spinner characters are erased
    sys.stdout.write(f"\r{GREEN}✔{RESET} {message.strip()} {GREEN}done!{RESET}       \n")
    sys.stdout.flush()
    
    return result
