"""
Automation script for roadbook: {name} ({rb_id})
Generated by Roadbook CLI at {date_str}.

[AGENT INSTRUCTION - BEST PRACTICES]
1. Selectors: Prefer semantic locators (e.g., `page.get_by_role()`, `page.get_by_text()`) over brittle XPath/CSS.
2. Variables: DO NOT hardcode search queries or credentials. Extract them to the `inputs` dict.
3. Artifacts: Save all screenshots, downloads, and extracted data to the `output_dir`.
4. Testing: Use the `tests/` directory for micro-testing complex UI elements before merging here.

[AGENT INSTRUCTION - AARP TRANSLATION GUIDE]
When syncing this script back to roadbook.md, use these mappings:
- `page.goto(url)` -> `GOTO "url"`
- `page.click(sel)` -> `CLICK "sel"`
- `page.fill(sel, val)` -> `INPUT "sel" "val"`
- `page.wait_for_selector(sel)` -> `WAIT "sel"`
"""
import sys
import json
import logging
import time
import os
from pathlib import Path
from contextlib import contextmanager

# Add current directory to path so we can import utils
sys.path.append(str(Path(__file__).parent))

try:
    from utils.browser import get_playwright_context, wait_for_page_load, get_project_root, get_storage_state_path
except ImportError:
        # Fallback if utils not present or path issue
        def wait_for_page_load(page, strategy="domcontentloaded", timeout=None):
            if timeout is None:
                try:
                    from roadbook.core.config import load_config
                    timeout = load_config().get("scaffold", {}).get("default_timeout", 10000)
                except ImportError:
                    timeout = 10000
            try:
                page.wait_for_load_state(strategy, timeout=timeout)
            except:
                pass

        def get_playwright_context(headless=None, cdp_url=None, storage_state_path=None):
            from playwright.sync_api import sync_playwright
            browser_type_name = "chromium"
            if headless is None:
                try:
                    from roadbook.core.config import load_config
                    browser_config = load_config().get("scaffold", {})
                    headless = browser_config.get("headless", False)
                    browser_type_name = browser_config.get("browser_type", "chromium")
                except ImportError:
                    headless = False
            p = sync_playwright().start()
            playwright_browser_type = getattr(p, browser_type_name, p.chromium)
            if cdp_url:
                browser = playwright_browser_type.connect_over_cdp(cdp_url)
                context = browser.contexts[0] if browser.contexts else browser.new_context()
                page = context.pages[0] if context.pages else context.new_page()
                return p, browser, context, page, {"mode": "cdp", "file": None}
            else:
                browser = playwright_browser_type.launch(headless=headless)
                if storage_state_path and os.path.exists(storage_state_path):
                    context = browser.new_context(storage_state=storage_state_path)
                    return p, browser, context, page, {"mode": "storage", "file": storage_state_path}
                else:
                    context = browser.new_context()
                page = context.new_page()
                return p, browser, context, page, {"mode": "fresh", "file": None}
# Configure Logging
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    handlers=[
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)

# Step Profiling Helper
STEPS_TIMING = {}

@contextmanager
def step(name):
    logger.info(f"[*] Step Started: {name}...")
    start_time = time.time()
    try:
        yield
    finally:
        duration = time.time() - start_time
        STEPS_TIMING[name] = duration
        logger.info(f"    -> Step Finished: {name} (Duration: {duration:.2f}s)")

def print_scaffold_warning():
    """Prints a warning that this is a scaffold script."""
    print("==============================================================================")
    print("                     Roadbook Scaffold Execution                              ")
    print("==============================================================================")
    print("  NOTICE: You are running a scaffold script.                                  ")
    print("  This script contains structure but NO scraping logic yet.                   ")
    print("                                                                              ")
    print("  Workflow Options:                                                           ")
    print("  [Option A] Human-Guided (Recommended for complex flows):                    ")
    print("    1. Run 'roadbook edit <id>' to visually outline steps in roadbook.md.     ")
    print("    2. Implement the corresponding logic in 'scripts/script.py'.              ")
    print("                                                                              ")
    print("  [Option B] AI-Driven Exploration:                                           ")
    print("    Command your AI Agent to explore the webpage directly. The agent can      ")
    print("    write code or use browser tools to map the flow, refining both            ")
    print("    'scripts/script.py' and 'roadbook.md' simultaneously.                     ")
    print("==============================================================================")

# ---------------------------------------------------------
# Output Management Helpers
# Provides multiple data export forms for agents to choose from.
# ---------------------------------------------------------
def save_as_json(data: dict, output_dir: Path, filename="outputs.json") -> str:
    path = output_dir / filename
    with open(path, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    return str(path)

def save_as_csv(items: list, output_dir: Path, filename="outputs.csv") -> str:
    if not items: return ""
    import csv
    path = output_dir / filename
    with open(path, "w", newline="", encoding="utf-8-sig") as f:
        writer = csv.DictWriter(f, fieldnames=items[0].keys())
        writer.writeheader()
        writer.writerows(items)
    return str(path)

def save_as_markdown(content: str, output_dir: Path, filename="outputs.md") -> str:
    path = output_dir / filename
    with open(path, "w", encoding="utf-8") as f:
        f.write(content)
    return str(path)

def run(inputs: dict) -> dict:
    """
    Main execution entry point.
    """
    # TODO: [AGENT INSTRUCTION] 
    # If this script is purely a generated scaffold without implemented scraping/automation logic,
    # leave this warning to inform the user. 
    # If you HAVE implemented the core logic, please remove or comment out this warning.
    print_scaffold_warning()
    logger.info(f"Starting execution for {inputs}")
    
    # entry_url can be overridden by inputs, otherwise use the one defined in Roadbook
    entry_url = inputs.get("entry_url", "{entry_url_fallback}")
    data = {}
    
    # Runtime artifacts setup
    # If run by CLI, ROADBOOK_RUN_ID will be set.
    session_id = os.environ.get("ROADBOOK_RUN_ID")
    
    # Locate the outputs directory (sibling to scripts/)
    project_root = Path(__file__).parent.parent
    outputs_root = project_root / "outputs"
    
    if not session_id:
        # Manual run fallback
        timestamp = time.strftime('%Y%m%d_%H%M%S')
        session_id = f"run_{timestamp}"
        
    output_dir = outputs_root / session_id
    output_dir.mkdir(parents=True, exist_ok=True)
    logger.info(f"Artifacts will be saved to: {output_dir}")

    try:
        # --- BROWSER SESSION STRATEGY ---
        # TODO: Check if this roadbook relies on an existing login state (cookies/localStorage).
        # Strategy 1: Use CDP to connect to an already logged-in browser (DEBUG / DEV)
        #    - Launch Chrome with flag: --remote-debugging-port=9222
        #    - Pass input: {"cdp_url": "http://localhost:9222"}
        # Strategy 2: Persistent Profile (Keep cookies/storage across runs automatically)
        #    - Pass input: {"user_data_dir": "my_profile"} -> Saved to `<root>/.browser/profiles/my_profile`
        # Strategy 3: Use a saved storage state file (CI / PROD)
        #    - Generate state file once (e.g., auth.json)
        #    - Pass input: {"storage_state": "auth.json"} -> Saved to/loaded from `<root>/.browser/auth.json`
        # Strategy 4: Fresh Browser (Default)
        
        # Attempt to get config from inputs
        cdp_url = inputs.get("cdp_url")
        storage_state = inputs.get("storage_state")
        user_data_dir = inputs.get("user_data_dir")

        # Initialize Browser
        p, browser, context, page, ctx_info = get_playwright_context(cdp_url=cdp_url, storage_state_path=storage_state, user_data_dir=user_data_dir)
        logger.info(f"Browser Mode: {ctx_info['mode']}")
        
        try:
{logic_body}
            
            logger.info("All steps completed successfully")
            
            # Update session state if in storage mode
            if ctx_info["mode"] == "storage" and ctx_info["file"]:
                try:
                    context.storage_state(path=ctx_info["file"])
                    logger.info(f"Updated session state: {ctx_info['file']}")
                except Exception as e:
                    logger.warning(f"Failed to update session state: {e}")
            
        except Exception as step_err:
            logger.error(f"Error during execution steps: {step_err}")
            error_screenshot_path = output_dir / "error_screenshot.png"
            try:
                page.screenshot(path=str(error_screenshot_path))
                logger.info(f"Saved error screenshot to {error_screenshot_path}")
            except Exception as ss_err:
                logger.error(f"Failed to take error screenshot: {ss_err}")
            raise step_err
            
        finally:
            browser.close()
            p.stop()
            
        # Attach timing metrics to data
        data["_steps_timing"] = STEPS_TIMING
        
        # ---------------------------------------------------------
        # AGENT EXPORT INSTRUCTIONS: Choose the appropriate outputs.
        # ---------------------------------------------------------
        
        # 1. JSON (Structured default record)
        save_as_json(data, output_dir, "outputs.json")
        
        # 2. CSV: Excellent for multiple rows/items
        # if "items" in data and isinstance(data["items"], list):
        #     save_as_csv(data["items"], output_dir, "table_data.csv")
        
        # 3. Markdown: Excellent for text, articles, readability
        # if "article" in data:
        #     save_as_markdown(data["article"], output_dir, "document.md")
        
        # 4. Quick Answer / Summary (Passed directly back to the User/LLM)
        # data["quick_answer"] = "Action completed. 15 items extracted."
        
        # 5. Multimedia/File paths (Make sure to save the absolute paths)
        # screenshot_path = output_dir / "final_state.png"
        # page.screenshot(path=str(screenshot_path), full_page=True)
        # data["final_screenshot"] = str(screenshot_path)
        
        return {"status": "success", "data": data}

    except Exception as e:
        logger.error(f"Execution failed: {e}", exc_info=True)
        return {"status": "failed", "error": str(e)}

# ---------------------------------------------------------
# INPUT PARAMETERS DEFINITION
# ---------------------------------------------------------
# TODO: Agent should define the script's input parameters here.
# This helps users understand what parameters can be passed to this script.
# Example:
# EXPECTED_INPUTS = {
#     "city": {"type": "string", "required": True, "description": "The city to search for"},
#     "date": {"type": "string", "required": False, "default": "today", "description": "The date of travel"},
# }
EXPECTED_INPUTS = {
    # Define parameters here
}

if __name__ == "__main__":
    # Standard Entry Point for CLI Execution
    try:
        if len(sys.argv) > 1:
            try:
                # Try parsing as JSON first
                cli_inputs = json.loads(sys.argv[1])
            except json.JSONDecodeError:
                # If not JSON, maybe treat as key=value or just empty
                cli_inputs = {}
        else:
             cli_inputs = {}
        
        # Print expected inputs and default values
        if EXPECTED_INPUTS:
            logger.info("--- Expected Input Parameters ---")
            for key, param in EXPECTED_INPUTS.items():
                req_status = "Required" if param.get("required") else f"Optional (Default: {param.get('default')})"
                logger.info(f"  - {key} ({param.get('type', 'any')}): {param.get('description', '')} [{req_status}]")
            logger.info("---------------------------------")
            
        # Check required parameters and apply defaults
        missing_params = []
        for key, param in EXPECTED_INPUTS.items():
            if param.get("required") and key not in cli_inputs:
                missing_params.append(key)
            elif not param.get("required") and key not in cli_inputs and "default" in param:
                cli_inputs[key] = param["default"]
                
        if missing_params:
            logger.error(f"Missing required parameters: {', '.join(missing_params)}")
            logger.error("Please provide them via JSON string as the first argument.")
            logger.error("Example: roadbook run <id> '{\"param1\": \"value1\"}'")
            sys.exit(1)
            
        if not cli_inputs and EXPECTED_INPUTS:
            logger.info("No inputs provided. Using default parameters if any.")
        elif not cli_inputs:
            logger.info("No inputs provided. Running with empty parameters.")
        else:
            logger.info(f"Running with inputs: {cli_inputs}")
        
        result = run(cli_inputs)
        
        # Ensure result is printed to stdout for capture
        # Truncate output if it's too long to avoid flooding the terminal
        result_json = json.dumps(result, ensure_ascii=False)
        if len(result_json) > 1000:
            print(result_json[:1000] + "\n... [Result truncated. Please check outputs.json for full details]")
        else:
            print(result_json)
        
    except Exception as e:
        print(json.dumps({"status": "failed", "error": str(e)}))
        sys.exit(1)
