import { readFile, writeFile } from 'node:fs/promises';
import { execFileSync } from 'node:child_process';
import { expect } from 'e2e';
import { test, WEB } from './t3.ts';
import { T3_HOME } from '../e2e.config.ts';

const pause = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

test('Sidebar shortcuts honor terminal focus, preview focus and open panels', WEB, async ({t3, app, browser, screen}) => {
  await writeFile(`${T3_HOME}/userdata/keybindings.json`, JSON.stringify([
    {key:'mod+b',command:'sidebar.toggle',when:'!terminalFocus'},
    {key:'mod+alt+1',command:'sidebar.toggle',when:'terminalOpen'},
    {key:'mod+alt+2',command:'sidebar.toggle',when:'previewOpen'},
    {key:'mod+alt+3',command:'sidebar.toggle',when:'previewFocus'},
    {key:'mod+alt+4',command:'sidebar.toggle',when:'!previewFocus'},
  ]));
  const project = await t3.project('Shortcut proof', {'.tmux.conf': `set -g status-left '[proof] '\nset -g status-right 'Sidebar shortcut proof'\nset -g status-interval 0\nset -g default-shell /bin/bash\nset -g default-command 'env PS1="proof$ " bash --noprofile --norc'\nset -g allow-rename off\n`});
  const thread = await t3.thread({project,title:'Sidebar shortcut proof',messages:['Show the shortcut proof workspace.']});
  await browser.emulateMedia({reducedMotion:'reduce',colorScheme:'dark'});
  await t3.open(thread);
  const sidebar = browser.locator('[data-slot="sidebar-wrapper"]');
  const state = () => sidebar.getAttribute('data-sidebar-state');
  const observations: Record<string, boolean> = {};
  const expanded = async () => {
    if (await state() !== 'expanded') await screen.getByRole('button','Toggle main sidebar', {exact:true}).tap();
  };
  const capture = async (label: string) => {
    await browser.mouse.move(640, 60);
    await pause(1800);
    let prev = await app.screenshot(`${label}-settle`);
    for (let n=0;n<8;n++) {
      await pause(500);
      const next = await app.screenshot(label);
      if ((await readFile(prev)).equals(await readFile(next))) return;
      prev = next;
    }
    throw new Error(`Capture ${label} did not settle`);
  };
  const conversation = async () => {
    await browser.locator('[contenteditable="true"]').first().tap();
  };
  const terminal = async () => {
    await browser.locator('[data-terminal-owner="drawer"] canvas').tap();
  };
  const socket = `sidebar-proof-${Date.now()}`;
  const tmux = (...args: string[]) => execFileSync('tmux',['-L',socket,...args],{encoding:'utf8'}).trim();
  try {
    await screen.getByRole('button','Toggle terminal drawer',{exact:true}).tap();
    await terminal();
    await browser.keyboard.type(`tmux -L ${socket} -f .tmux.conf new-session -s proof`);
    await browser.keyboard.press('Enter');
    for(let n=0;n<50;n++) {
      try {if(tmux('list-windows').length) break;} catch {}
      await pause(100);
    }
    await pause(1500);
    await browser.keyboard.press('Control+b');
    await browser.keyboard.press('c');
    await pause(1500);
    observations.terminalFocusLeavesSidebarExpanded = await state() === 'expanded';
    observations.tmuxReceivesPrefix = tmux('list-windows','-F','#{window_index}').split('\n').length === 2;
    await browser.keyboard.press('Control+u');
    await browser.keyboard.type(`tmux list-windows -F 'window #{window_index}: #{window_name}'`);
    await browser.keyboard.press('Enter');
    await capture('01-terminal-focus-ctrl-b-c');

    await expanded();
    await conversation();
    await browser.keyboard.press('Control+b');
    await pause(700);
    observations.conversationCtrlBToggles = await state() === 'collapsed';
    await capture('02-conversation-ctrl-b');

    await expanded();
    await conversation();
    await browser.keyboard.press('Control+Alt+1');
    await pause(700);
    observations.terminalOpenPositiveMatches = await state() === 'collapsed';
    await capture('03-terminal-open-positive');

    await expanded();
    await screen.getByRole('button','Toggle terminal drawer',{exact:true}).tap();
    await conversation();
    await browser.keyboard.press('Control+Alt+1');
    await pause(700);
    observations.terminalClosedDoesNotMatch = await state() === 'expanded';
    await capture('04-terminal-closed-control');

    await browser.keyboard.press('Control+Shift+j');
    await screen.getByRole('textbox','Search or enter URL',{exact:true}).tap();
    await browser.keyboard.press('Control+Alt+3');
    await pause(700);
    observations.previewFocusPositiveMatches = await state() === 'collapsed';
    await capture('05-preview-focus-positive');

    await expanded();
    await screen.getByRole('textbox','Search or enter URL',{exact:true}).tap();
    await browser.keyboard.press('Control+Alt+4');
    await pause(700);
    observations.previewFocusNegativeDoesNotMatch = await state() === 'expanded';
    await capture('06-preview-focus-negative');

    await expanded();
    await conversation();
    await browser.keyboard.press('Control+Alt+2');
    await pause(700);
    observations.previewOpenPositiveMatches = await state() === 'collapsed';
    await capture('07-preview-open-positive');

    await expanded();
    await conversation();
    await browser.keyboard.press('Control+Alt+3');
    await pause(700);
    observations.previewNotFocusedDoesNotMatch = await state() === 'expanded';
    await browser.keyboard.press('Control+Alt+4');
    await pause(700);
    observations.outsidePreviewNegativeMatches = await state() === 'collapsed';
    await capture('08-outside-preview-control');

    await expanded();
    await conversation();
    await browser.keyboard.press('Control+Shift+j');
    await conversation();
    await browser.keyboard.press('Control+Alt+2');
    await pause(700);
    observations.previewClosedDoesNotMatch = await state() === 'expanded';
    await capture('09-preview-closed-control');
    console.log('SHORTCUT_OBSERVATIONS',JSON.stringify(observations));
    expect(observations).toEqual(Object.fromEntries(Object.keys(observations).map(key=>[key,true])));
  } finally {
    try {tmux('kill-server');} catch {}
  }
});
