"""Verify ortho mode + redo + toolbar redesign:
1. Toolbar = Tags / Snap / Ortho / Undo / Redo (no Camera/Gallery)
2. Ortho ON: diagonal drag commits a horizontal or vertical line
3. Ortho OFF: diagonal drag commits a diagonal line
4. Undo/Redo restore the line
"""
import os
import sys
import time

sys.stdout.reconfigure(encoding="utf-8", errors="replace")

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service

HERE = os.path.dirname(os.path.abspath(__file__))
GECKODRIVER = os.path.join(HERE, "geckodriver.exe")
BASE = "http://localhost:8000/field-capture.html?debug"

DRAW_JS = """
(function(startX, startY, endX, endY, pointerId){
  const canvas = document.getElementById('sketchCanvas');
  canvas.setPointerCapture = function(){};
  canvas.releasePointerCapture = function(){};
  canvas.hasPointerCapture = function(){ return false; };
  const rect = canvas.getBoundingClientRect();
  const opts = { bubbles: true, cancelable: true, pointerType: 'touch', isPrimary: true };
  const sx = rect.left + rect.width*startX, sy = rect.top + rect.height*startY;
  const ex = rect.left + rect.width*endX, ey = rect.top + rect.height*endY;
  canvas.dispatchEvent(new PointerEvent('pointerdown', Object.assign({}, opts, {pointerId: pointerId, clientX: sx, clientY: sy})));
  for (let i = 1; i <= 5; i++) canvas.dispatchEvent(new PointerEvent('pointermove', Object.assign({}, opts, {pointerId: pointerId, clientX: sx+(ex-sx)*i/5, clientY: sy+(ey-sy)*i/5})));
  canvas.dispatchEvent(new PointerEvent('pointerup', Object.assign({}, opts, {pointerId: pointerId, clientX: ex, clientY: ey})));
  return 'drawn';
})(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4]);
"""


def main():
    opts = Options()
    opts.headless = False
    svc = Service(executable_path=GECKODRIVER)
    d = webdriver.Firefox(options=opts, service=svc)
    d.set_window_size(480, 900)
    try:
        d.get(BASE)
        time.sleep(2)
        d.find_element(By.CSS_SELECTOR, '[data-action="newjob"]').click()
        time.sleep(0.8)
        d.find_element(By.CSS_SELECTOR, '[data-action="opensketch"]').click()
        time.sleep(0.8)
        d.execute_script("""
            const T = window.__test;
            const job = T.state.jobs[0];
            const sk = job.sketches[0];
            const c = document.createElement('canvas');
            c.width = 200; c.height = 150;
            const ctx = c.getContext('2d');
            ctx.fillStyle = '#cccccc'; ctx.fillRect(0,0,200,150);
            sk.photo = { dataUrl: c.toDataURL('image/jpeg', 0.8), width: 200, height: 150 };
            T.saveState();
        """)
        d.execute_script(
            "const T=window.__test; T.ui.screen='sketch'; T.ui.sketchId=T.state.jobs[0].sketches[0].id; T.render();"
        )
        time.sleep(0.8)

        # 1. Toolbar buttons
        print("toolbar buttons:", d.execute_script("""
            return JSON.stringify(Array.from(document.querySelectorAll('.sketch-toolbar .sketch-tool')).map(b => b.textContent.trim()));
        """))

        # 2. Ortho ON: draw a diagonal line, it should become horizontal/vertical
        d.find_element(By.CSS_SELECTOR, '[data-action="toggle-ortho"]').click()
        time.sleep(0.3)
        print("ortho on:", d.execute_script("const T=window.__test; return T.ui.orthoEnabled;"))
        d.execute_script(DRAW_JS, 0.3, 0.4, 0.7, 0.6, 11)
        time.sleep(0.6)
        # Close the quick sheet
        d.execute_script('document.querySelector(".sheet-minimal [data-action=closesheet]").click()')
        time.sleep(0.4)
        line1 = d.execute_script("""
            const T=window.__test; const l=T.state.jobs[0].sketches[0].lines[0];
            return JSON.stringify({start: l.start, end: l.end});
        """)
        print("ortho line (expect horizontal, same y):", line1)

        # 3. Ortho OFF: draw a diagonal line, it should stay diagonal
        d.find_element(By.CSS_SELECTOR, '[data-action="toggle-ortho"]').click()
        time.sleep(0.3)
        print("ortho off:", d.execute_script("const T=window.__test; return T.ui.orthoEnabled;"))
        d.execute_script(DRAW_JS, 0.2, 0.2, 0.6, 0.5, 12)
        time.sleep(0.6)
        d.execute_script('document.querySelector(".sheet-minimal [data-action=closesheet]").click()')
        time.sleep(0.4)
        line2 = d.execute_script("""
            const T=window.__test; const l=T.state.jobs[0].sketches[0].lines[1];
            return JSON.stringify({start: l.start, end: l.end});
        """)
        print("free line (expect diagonal, both axes differ):", line2)

        # 4. Undo then Redo
        print("lines before undo:", d.execute_script(
            "const T=window.__test; return T.state.jobs[0].sketches[0].lines.length;"
        ))
        d.find_element(By.CSS_SELECTOR, '[data-action="undo-line"]').click()
        time.sleep(0.4)
        print("lines after undo:", d.execute_script(
            "const T=window.__test; return T.state.jobs[0].sketches[0].lines.length;"
        ))
        print("redoStack size:", d.execute_script("const T=window.__test; return T.ui.redoStack.length;"))
        d.find_element(By.CSS_SELECTOR, '[data-action="redo-line"]').click()
        time.sleep(0.4)
        print("lines after redo:", d.execute_script(
            "const T=window.__test; return T.state.jobs[0].sketches[0].lines.length;"
        ))
        print("redoStack after redo:", d.execute_script("const T=window.__test; return T.ui.redoStack.length;"))
    finally:
        d.quit()


if __name__ == "__main__":
    main()