import test from "node:test";
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";

test("mobile composer controls use compact visuals with accessible touch targets", async () => {
  const menuCss = await readFile(new URL("./composer-menus.css", import.meta.url), "utf8");
  const conversationCss = await readFile(new URL("./conversation.css", import.meta.url), "utf8");

  assert.match(menuCss, /\.composer-pill > span\s*\{[^}]*min-height:\s*28px[^}]*padding:\s*0 6px[^}]*border:\s*0[^}]*background:\s*transparent/);
  assert.match(menuCss, /\.composer-quick-options\s*\{[^}]*bottom:\s*calc\(100% \+ 1px\)[^}]*height:\s*40px/);
  assert.match(menuCss, /@media \(max-width: 640px\)[\s\S]*\.composer-pill\s*\{[^}]*min-height:\s*48px[^}]*font-size:\s*12px/);
  assert.match(conversationCss, /\.composer\{[^}]*padding:0 18px calc\(18px \+ env\(safe-area-inset-bottom\)\)/);
  assert.match(conversationCss, /@media\(max-width:640px\)[^\n]*\.composer\{[^}]*padding:0 14px calc\(14px \+ env\(safe-area-inset-bottom\)\)/);
  assert.match(conversationCss, /@media\(max-width:640px\)[^\n]*\.composer-icon-button\{[^}]*min-height:56px/);
  assert.match(conversationCss, /@media\(max-width:640px\)[^\n]*\.composer-row\{[^}]*min-height:56px/);
  assert.match(conversationCss, /\.composer-input\{[^}]*min-height:56px[^}]*border-radius:28px[^}]*box-shadow:/);
  assert.match(conversationCss, /\.composer-row \.composer-icon-button,\.composer-row \.composer-send\{[^}]*border:0[^}]*background:transparent/);
  assert.match(conversationCss, /\.composer-action-icon\{[^}]*width:56px[^}]*height:56px/);
  assert.match(conversationCss, /\.composer-row\{[^}]*grid-template-columns:56px minmax\(0,1fr\) 56px/);
  assert.match(conversationCss, /\.composer-dock\{[^}]*position:absolute[^}]*left:0[^}]*right:0[^}]*bottom:0[^}]*background:transparent/);
  assert.match(conversationCss, /\.composer-action-icon\{[^}]*box-shadow:/);
  assert.match(conversationCss, /\.composer-action-svg\{[^}]*width:24px[^}]*height:24px/);
  assert.match(conversationCss, /@media\(max-width:640px\)[^\n]*\.composer button\{[^}]*min-height:56px/);
  assert.match(conversationCss, /\.composer-input:focus\{[^}]*outline:0[^}]*border-color:#50535e/);
});

test("queued message dock stays compact above the composer", async () => {
  const menuCss = await readFile(new URL("./composer-menus.css", import.meta.url), "utf8");
  const conversationCss = await readFile(new URL("./conversation.css", import.meta.url), "utf8");

  assert.match(menuCss, /\.composer-quick-options\s*\{[^}]*bottom:\s*calc\(100% \+ 1px\)/);
  assert.match(menuCss, /\.composer-pill\s*\{[^}]*align-items:\s*center/);
  assert.match(conversationCss, /\.composer-dock\{[^}]*display:grid/);
  assert.match(conversationCss, /\.queued-messages\{[^}]*position:absolute[^}]*width:max-content[^}]*overflow:visible/);
  assert.match(conversationCss, /\.queued-message\{[^}]*width:fit-content[^}]*min-height:30px[^}]*max-width:min\(82vw,720px\)[^}]*border-radius:999px/);
  assert.match(conversationCss, /\.queued-message>p\{[^}]*max-width:min\(62vw,520px\)/);
  assert.match(conversationCss, /\.queued-message-menu>summary\{[^}]*width:30px[^}]*height:30px[^}]*border-radius:50%/);
  assert.match(conversationCss, /\.queued-message-popover button\{[^}]*min-height:48px[^}]*background:transparent/);
});

test("model and permission menus escape quick-control overflow as compact mobile popups", async () => {
  const menuCss = await readFile(new URL("./composer-menus.css", import.meta.url), "utf8");

  assert.match(menuCss, /\.composer-quick-options:has\(\.composer-menu\[open\]\)\s*\{[^}]*overflow:\s*visible/);
  assert.match(menuCss, /\.model-popover\.compact-menu,[\s\S]*?\.permission-popover\.compact-menu,[\s\S]*?\.model-picker-popover\.compact-menu\s*\{[^}]*left:\s*50%[^}]*right:\s*auto[^}]*transform:\s*translateX\(-50%\)[^}]*width:\s*72vw[^}]*max-height:\s*64dvh/);
  assert.match(menuCss, /\.composer-popover\.compact-menu \.menu-option\s*\{[^}]*min-height:\s*6dvh[^}]*font-size:\s*1\.8dvh/);
});

test("light theme preserves selected and full-access menu visibility", async () => {
  const baseCss = await readFile(new URL("../../shared/styles/base.css", import.meta.url), "utf8");
  const menuCss = await readFile(new URL("./composer-menus.css", import.meta.url), "utf8");

  assert.match(menuCss, /\.menu-option\.selected\s*\{[^}]*background:\s*#303030/);
  assert.match(baseCss, /html\[data-theme="light"\] \.app-shell :is\(\.menu-option,\.tool-menu-row\):hover,html\[data-theme="light"\] \.app-shell :is\(\.menu-option,\.tool-menu-row\)\.selected\{[^}]*background:#eaeef2!important/);
  assert.match(baseCss, /\.permission-popover \.menu-option\.full-access\.selected\{[^}]*background:#fff8c5!important[^}]*color:#7a4b00!important/);
});

test("composer menus use SVG checks without right-side disclosure arrows", async () => {
  const [model, permission, tools, icons] = await Promise.all([
    readFile(new URL("./ComposerModelMenu.jsx", import.meta.url), "utf8"),
    readFile(new URL("./ComposerPermissionMenu.jsx", import.meta.url), "utf8"),
    readFile(new URL("./ComposerToolsMenu.jsx", import.meta.url), "utf8"),
    readFile(new URL("../../shared/ActionIcons.jsx", import.meta.url), "utf8")
  ]);

  assert.match(model, /CheckIcon/);
  assert.match(permission, /CheckIcon/);
  assert.equal((tools.match(/<CheckIcon \/>/g) ?? []).length, 2);
  assert.doesNotMatch(tools, /✓/);
  assert.doesNotMatch(model, /ChevronDownIcon/);
  assert.doesNotMatch(permission, /ChevronDownIcon/);
  assert.doesNotMatch(icons, /ChevronDownIcon/);
  assert.match(icons, /export function CheckIcon/);
});

test("all close and remove controls share the confirmed SVG close icon", async () => {
  const [icons, changes, context, activity, newChat, panel, gallery, workspace] = await Promise.all([
    readFile(new URL("../../shared/ActionIcons.jsx", import.meta.url), "utf8"),
    readFile(new URL("../changes/ChangeDiffSheet.jsx", import.meta.url), "utf8"),
    readFile(new URL("../context/ContextBar.jsx", import.meta.url), "utf8"),
    readFile(new URL("./ActivityCard.jsx", import.meta.url), "utf8"),
    readFile(new URL("../chats/NewChatPanel.jsx", import.meta.url), "utf8"),
    readFile(new URL("./ConversationPanel.jsx", import.meta.url), "utf8"),
    readFile(new URL("./ImageGallery.jsx", import.meta.url), "utf8"),
    readFile(new URL("./WorkspaceAttachPicker.jsx", import.meta.url), "utf8")
  ]);

  assert.match(icons, /export function CloseIcon/);
  assert.match(icons, /<X className=\{className\}/);
  for (const source of [changes, context, activity, newChat, panel, gallery, workspace]) {
    assert.match(source, /<CloseIcon \/>/);
    assert.doesNotMatch(source, />[×x]</);
  }
  assert.doesNotMatch(newChat, /composer-attachment-remove-icon/);
  assert.doesNotMatch(panel, /composer-attachment-remove-icon/);
});

test("model selection opens a separate compact picker popup", async () => {
  const model = await readFile(new URL("./ComposerModelMenu.jsx", import.meta.url), "utf8");

  assert.match(model, /modelPickerOpen/);
  assert.match(model, /className="composer-popover model-picker-popover compact-menu"/);
  assert.match(model, /model-picker-trigger/);
});

test("mobile model picker is not nested in the scrolling effort popover", async () => {
  const model = await readFile(new URL("./ComposerModelMenu.jsx", import.meta.url), "utf8");

  const effortPopoverEnd = model.indexOf("    </div>\n  </details>");
  const picker = model.indexOf("{modelPickerOpen && <div className=\"composer-popover model-picker-popover compact-menu\"");

  assert.ok(picker > effortPopoverEnd, "the picker must be a details child, outside the scrolling effort popover");
});

test("active tool chips match model and permission button surfaces in both themes", async () => {
  const [panel, icons, baseCss, menuCss] = await Promise.all([
    readFile(new URL("./ConversationPanel.jsx", import.meta.url), "utf8"),
    readFile(new URL("../../shared/ActionIcons.jsx", import.meta.url), "utf8"),
    readFile(new URL("../../shared/styles/base.css", import.meta.url), "utf8"),
    readFile(new URL("./composer-menus.css", import.meta.url), "utf8")
  ]);

  assert.match(panel, /<CloseIcon \/>/);
  assert.doesNotMatch(panel, /<b aria-hidden="true">x<\/b>/);
  assert.match(icons, /export function CloseIcon/);
  assert.match(baseCss, /\.composer-active-chip\{border:0!important;background:transparent!important;background-color:transparent!important;box-shadow:none!important/);
  assert.match(menuCss, /\.composer-active-chip\s*\{[^}]*border:\s*0[^}]*background:\s*transparent[^}]*box-shadow:\s*none/);
  assert.match(menuCss, /\.composer-menu > \.composer-pill > span,\s*\.composer-active-chip > span\s*\{[^}]*border:\s*1px solid #343841[^}]*background:\s*#202329[^}]*box-shadow:\s*0 1px 0 rgba\(255, 255, 255, \.04\)/);
  assert.match(baseCss, /\.composer-menu>\.composer-pill>span,html\[data-theme="light"\] \.app-shell \.composer-active-chip>span\{border:1px solid #d0d7de!important[^}]*background:#fff!important/);
});
