import os
import zipfile
import requests
import base64
from .config import get_app_id, load_local_config
from .utils import print_success, print_info, print_error, run_with_spinner

GITHUB_API_URL = "https://api.github.com"
BUILD_REPO_OWNER = "juniorsir" 
BUILD_REPO_NAME = "appforge-build"
MASTER_SYSTEM_TOKEN = "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" # <-- PUT YOUR TOKEN HERE

def get_headers():
    return {
        "Authorization": f"Bearer {MASTER_SYSTEM_TOKEN}",
        "Accept": "application/vnd.github.v3+json",
        "X-GitHub-Api-Version": "2022-11-28"
    }

# ... (imports and constants at the top stay the same) ...

def zip_project(category, zip_name="app_source.zip"):
    """Zips the project, intelligently ignoring folders based on project category."""
    def do_zip():
        # --- THIS IS THE NEW INTELLIGENT IGNORE LOGIC ---
        if category == 'web':
            # For web projects, we ignore the heavy native folders
            ignore_list = ['node_modules', '.git', 'android', 'ios', '.next', '.nuxt', 'build', 'dist']
        else: # This applies to 'native' projects (Flutter, Kotlin, etc.)
            # For native projects, we MUST include the android/ios folders,
            # but ignore caches and build artifacts.
            ignore_list = ['node_modules', '.git', '.dart_tool', 'build', '.gradle']

        with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
            for root, dirs, files in os.walk('.'):
                dirs[:] = [d for d in dirs if d not in ignore_list]
                for file in files:
                    if file == zip_name:
                        continue
                    file_path = os.path.join(root, file)
                    zipf.write(file_path, file_path)
    
    run_with_spinner(do_zip, "Zipping project files")
    return zip_name

def push_and_build(config):
    """Pushes the zipped project and triggers the cloud build."""
    # Extract needed info from the config
    category = config.get("category", "web")
    platform = config.get("platform", "android")
    app_id = get_app_id()

    # Pass the category to the zipping function
    zip_path = zip_project(category)
    
    headers = get_headers()
    
    def do_upload():
        with open(zip_path, "rb") as f:
            content_b64 = base64.b64encode(f.read()).decode("utf-8")
        
        url = f"{GITHUB_API_URL}/repos/{BUILD_REPO_OWNER}/{BUILD_REPO_NAME}/contents/apps/{app_id}/source.zip"
        
        sha = None
        res = requests.get(url, headers=headers)
        if res.status_code == 200: sha = res.json().get("sha")

        data = {"message": f"Upload for {app_id}", "content": content_b64, "branch": "main"}
        if sha: data["sha"] = sha
        
        put_res = requests.put(url, headers=headers, json=data)
        if put_res.status_code not in [200, 201]:
            raise Exception(f"Failed to upload: {put_res.json().get('message')}")
            
    run_with_spinner(do_upload, f"Uploading app (ID: {app_id})")
    os.remove(zip_path)

    def do_trigger():
        # Load the full config again just to be safe
        full_config = load_local_config()
        proj_category = full_config.get("category", "web")
        proj_type = full_config.get("project_type", "unknown")
        
        dispatch_url = f"{GITHUB_API_URL}/repos/{BUILD_REPO_OWNER}/{BUILD_REPO_NAME}/actions/workflows/build.yml/dispatches"
        
        dispatch_data = {
            "ref": "main", 
            "inputs": {
                "app_id": app_id, 
                "platform": platform,
                "project_category": proj_category,
                "project_type": proj_type
            }
        }
        res = requests.post(dispatch_url, headers=headers, json=dispatch_data)
        if res.status_code != 204:
            raise Exception(f"Failed to trigger build. Status {res.status_code}: {res.text}")

    run_with_spinner(do_trigger, "Triggering cloud build")

def check_status():
    """Streams live build logs from GitHub Actions to the terminal."""
    headers = get_headers()
    
    # 1. Find the most recent workflow run
    url = f"{GITHUB_API_URL}/repos/{BUILD_REPO_OWNER}/{BUILD_REPO_NAME}/actions/runs?per_page=1"
    res = requests.get(url, headers=headers)
    
    if res.status_code != 200:
        print_error("Could not fetch build status from cloud.")
        return

    runs = res.json().get("workflow_runs", [])
    if not runs:
        print_info("No builds found in the cloud yet.")
        return
    
    latest_run = runs[0]
    run_id = latest_run["id"]
    status = latest_run["status"]
    
    if status == "completed":
        conclusion = latest_run.get("conclusion")
        if conclusion == "success":
            print_success(f"Build #{run_id} is already completed! Run 'appforge download'")
        else:
            print_error(f"Build #{run_id} failed with conclusion: {conclusion}")
        return

    print_info(f"Connected to Cloud Build #{run_id}. Streaming live logs...\n")
    print("-" * 50)

    # 2. Find the active "Job" inside the run (e.g., 'build-android' or 'build-ios')
    jobs_url = f"{GITHUB_API_URL}/repos/{BUILD_REPO_OWNER}/{BUILD_REPO_NAME}/actions/runs/{run_id}/jobs"
    
    last_step_name = ""
    
    # 3. The Live Streaming Loop
    try:
        while True:
            jobs_res = requests.get(jobs_url, headers=headers)
            if jobs_res.status_code != 200:
                time.sleep(3)
                continue
                
            jobs = jobs_res.json().get("jobs", [])
            if not jobs:
                time.sleep(3)
                continue
                
            active_job = jobs[0] # Monitor the first job for simplicity
            
            # Print the current step the server is executing
            steps = active_job.get("steps", [])
            for step in steps:
                if step["status"] == "in_progress" and step["name"] != last_step_name:
                    
                    # Highlight our custom Permission Injector step!
                    if "Permission" in step["name"]:
                        print(f"{CYAN}⚙️  [Cloud] {step['name']}...{RESET}")
                    else:
                        print(f"{GRAY}▶  [Cloud] {step['name']}...{RESET}")
                        
                    last_step_name = step["name"]
                    break # Only print the currently running step

            # Check if the whole job finished
            if active_job["status"] == "completed":
                print("-" * 50)
                if active_job["conclusion"] == "success":
                    print_success("\n✨ Cloud Build Finished Successfully!")
                    print_info("Run 'appforge download' to get your app.")
                else:
                    print_error("\n❌ Cloud Build Failed. Check GitHub for full error logs.")
                break
                
            # Wait 3 seconds before polling GitHub again to avoid API rate limits
            time.sleep(3)
            
    except KeyboardInterrupt:
        print(f"\n{YELLOW}⚠ Stopped watching logs. The build is still running in the cloud.{RESET}")
        print_info("You can run 'appforge status' again later to reconnect.")

def download_apk():
    app_id = get_app_id()
    headers = get_headers()
    url = f"{GITHUB_API_URL}/repos/{BUILD_REPO_OWNER}/{BUILD_REPO_NAME}/actions/artifacts?per_page=100"
    res = requests.get(url, headers=headers)
    
    if res.status_code == 200:
        artifacts = res.json().get("artifacts", [])
        found = False
        
        for artifact in artifacts:
            name = artifact.get("name")
            if name in [f"appforge-apk-{app_id}", f"appforge-ios-{app_id}"]:
                found = True
                print_success(f"Found artifact: {name}")
                secure_api_url = artifact.get('archive_download_url')
                redirect_res = requests.get(secure_api_url, headers=headers, allow_redirects=False)
                if redirect_res.status_code == 302:
                    print_info(f"Download link (expires in 1 min):\n{redirect_res.headers['Location']}\n")
                
        if not found:
            print_error("Build not finished yet, or artifact not found.")
    else:
        print_error("Failed to fetch artifacts.")
