import test from "node:test";
import assert from "node:assert/strict";
import {
  runStartupBootstrapRuntimeService,
} from "./startup-service";
import { CliArgs } from "../../cli/args";

function makeArgs(overrides: Partial<CliArgs> = {}): CliArgs {
  return {
    start: false,
    stop: false,
    toggle: false,
    toggleVisibleOverlay: false,
    toggleInvisibleOverlay: false,
    settings: false,
    show: false,
    hide: false,
    showVisibleOverlay: false,
    hideVisibleOverlay: false,
    showInvisibleOverlay: false,
    hideInvisibleOverlay: false,
    copySubtitle: false,
    copySubtitleMultiple: false,
    mineSentence: false,
    mineSentenceMultiple: false,
    updateLastCardFromClipboard: false,
    refreshKnownWords: false,
    toggleSecondarySub: false,
    triggerFieldGrouping: false,
    triggerSubsync: false,
    markAudioCard: false,
    openRuntimeOptions: false,
    texthooker: false,
    help: false,
    autoStartOverlay: false,
    generateConfig: false,
    backupOverwrite: false,
    verbose: false,
    ...overrides,
  };
}

test("runStartupBootstrapRuntimeService configures startup state and starts lifecycle", () => {
  const calls: string[] = [];
  const args = makeArgs({
    verbose: true,
    socketPath: "/tmp/custom.sock",
    texthookerPort: 9001,
    backend: "x11",
    autoStartOverlay: true,
    texthooker: true,
  });

  const result = runStartupBootstrapRuntimeService({
    argv: ["node", "main.ts", "--verbose"],
    parseArgs: () => args,
    setLogLevel: (level, source) => calls.push(`setLog:${level}:${source}`),
    forceX11Backend: () => calls.push("forceX11"),
    enforceUnsupportedWaylandMode: () => calls.push("enforceWayland"),
    getDefaultSocketPath: () => "/tmp/default.sock",
    defaultTexthookerPort: 5174,
    runGenerateConfigFlow: () => false,
    startAppLifecycle: () => calls.push("startLifecycle"),
  });

  assert.equal(result.initialArgs, args);
  assert.equal(result.mpvSocketPath, "/tmp/custom.sock");
  assert.equal(result.texthookerPort, 9001);
  assert.equal(result.backendOverride, "x11");
  assert.equal(result.autoStartOverlay, true);
  assert.equal(result.texthookerOnlyMode, true);
  assert.deepEqual(calls, [
    "setLog:debug:cli",
    "forceX11",
    "enforceWayland",
    "startLifecycle",
  ]);
});

test("runStartupBootstrapRuntimeService prefers --log-level over --verbose", () => {
  const calls: string[] = [];
  const args = makeArgs({
    logLevel: "warn",
    verbose: true,
  });

  runStartupBootstrapRuntimeService({
    argv: ["node", "main.ts", "--log-level", "warn", "--verbose"],
    parseArgs: () => args,
    setLogLevel: (level, source) => calls.push(`setLog:${level}:${source}`),
    forceX11Backend: () => calls.push("forceX11"),
    enforceUnsupportedWaylandMode: () => calls.push("enforceWayland"),
    getDefaultSocketPath: () => "/tmp/default.sock",
    defaultTexthookerPort: 5174,
    runGenerateConfigFlow: () => false,
    startAppLifecycle: () => calls.push("startLifecycle"),
  });

  assert.deepEqual(calls.slice(0, 3), [
    "setLog:warn:cli",
    "forceX11",
    "enforceWayland",
  ]);
});

test("runStartupBootstrapRuntimeService skips lifecycle when generate-config flow handled", () => {
  const calls: string[] = [];
  const args = makeArgs({ generateConfig: true, logLevel: "warn" });

  const result = runStartupBootstrapRuntimeService({
    argv: ["node", "main.ts", "--generate-config"],
    parseArgs: () => args,
    setLogLevel: (level, source) => calls.push(`setLog:${level}:${source}`),
    forceX11Backend: () => calls.push("forceX11"),
    enforceUnsupportedWaylandMode: () => calls.push("enforceWayland"),
    getDefaultSocketPath: () => "/tmp/default.sock",
    defaultTexthookerPort: 5174,
    runGenerateConfigFlow: () => true,
    startAppLifecycle: () => calls.push("startLifecycle"),
  });

  assert.equal(result.mpvSocketPath, "/tmp/default.sock");
  assert.equal(result.texthookerPort, 5174);
  assert.equal(result.backendOverride, null);
  assert.deepEqual(calls, [
    "setLog:warn:cli",
    "forceX11",
    "enforceWayland",
  ]);
});
