/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import assert from 'node:assert/strict';
import { registerHooks } from 'node:module';
import test from 'node:test';

// Production Settings, locale and receipt handling run unchanged. Only native
// input state, element builders and the Host boundary are supplied by the test.
const nativeModules = {
  'gpui-kit': `const ui = (...args) => globalThis[Symbol.for('language.test.element')](...args);
    export { ui as div, ui as list, ui as svg, ui as uniform_list, ui as PathBuilder };
    export class View {}`,
  'gpui-base': `const ui = (...args) => globalThis[Symbol.for('language.test.element')](...args);
    const state = { new: ({placeholder}) => ({
      placeholder, on() {}, set_masked() {}, set_auto_grow() {}, value: () => '',
      set_placeholder(value) { this.placeholder = value; }
    }) };
    export { state as InputState, state as TextareaState };
    export const Button = { new: ui };
    export { ui as v_flex, ui as h_flex, ui as TextView, ui as Scrollbar,
      ui as set_theme, ui as Input, ui as Checkbox, ui as Switch,
      ui as Popover, ui as Textarea, ui as h_resizable, ui as resizable_panel };`,
  'maka-locale': `export const system = () => 'en';`,
  'maka-files': `const unexpected = () => { throw new Error('unexpected native file call'); };
    export { unexpected as openText, unexpected as chooseFolder, unexpected as chooseFiles,
      unexpected as release, unexpected as open, unexpected as reveal };`,
  'maka-desktop': `export const Terminal = {}; export const TerminalState = {};`,
  'maka-host': `export const query = (...args) => globalThis[Symbol.for('language.test.query')](...args);
    export const mutate = (...args) => globalThis[Symbol.for('language.test.mutate')](...args);
    const unexpected = () => { throw new Error('unexpected native subscription'); };
    export { unexpected as subscribe, unexpected as next, unexpected as close };`,
};
const hooks = registerHooks({
  resolve(specifier, context, nextResolve) {
    if (Object.hasOwn(nativeModules, specifier)) {
      return { url: `language-test:${specifier}`, shortCircuit: true };
    }
    return nextResolve(specifier, context);
  },
  load(url, context, nextLoad) {
    if (url.startsWith('language-test:')) {
      return { format: 'module', source: nativeModules[url.slice(14)], shortCircuit: true };
    }
    return nextLoad(url, context);
  },
});
const { Settings, settingsPage } = await import(
  '../../products/maka/desktop-shell/app/settings.js'
);
const { default: MakaDesktop } = await import('../../products/maka/desktop-shell/app/main.js');
const { language, t } = await import('../../products/maka/desktop-shell/app/locale.js');
hooks.deregister();

function setup(preferences) {
  const requests = [];
  const reports = [];
  const read = async (endpoint, method, input) => {
    requests.push({ endpoint, method, input });
    assert.equal(endpoint, 'settings');
    switch (method) {
      case 'assistantPreferences':
        return preferences;
      case 'connections':
        return { kind: 'ready', revision: 0, connections: [], next: null };
      case 'models':
        return {
          kind: 'ready',
          revision: 0,
          choices: [],
          defaultModel: { kind: 'none' },
          next: null,
        };
      default:
        throw new Error(`unexpected query ${method}`);
    }
  };
  globalThis[Symbol.for('language.test.query')] = read;
  globalThis[Symbol.for('language.test.mutate')] = () => {
    throw new Error('unexpected mutation');
  };
  const settings = new Settings({
    changed() {},
    report: (message) => reports.push(message),
    modelsChanged() {},
    presetsChanged() {},
  });
  return { settings, requests, reports, read };
}

test('opening Settings uses the Host language for labels and retained inputs', async () => {
  const { settings, requests, reports } = setup({
    revision: 7,
    language: null,
    resolvedLanguage: 'zh-TW',
  });
  await settings.load();
  assert.equal(language(), 'zh-TW');
  assert.equal(t('newTask'), '新任務');
  assert.equal(settings.modelQuery.placeholder, '搜尋模型');
  assert.equal(settings.preferences.language, null);
  assert.deepEqual(
    requests.filter((request) => request.method === 'assistantPreferences'),
    [{ endpoint: 'settings', method: 'assistantPreferences', input: {} }],
  );
  assert.deepEqual(reports, []);
});

function deferred() {
  let resolve;
  const promise = new Promise((done) => {
    resolve = done;
  });
  return { promise, resolve };
}

function returned(value) {
  return { receipt: { kind: 'recorded', outcome: { kind: 'returned', value } } };
}

test('save sends one CAS mutation and applies only the confirmed readback', async () => {
  const { settings } = setup({ revision: 10, language: 'en', resolvedLanguage: 'en' });
  await settings.loadPreferences();
  const mutation = deferred();
  const reading = deferred();
  const snapshot = deferred();
  const mutations = [];
  globalThis[Symbol.for('language.test.mutate')] = (...args) => {
    mutations.push(args);
    return mutation.promise;
  };
  globalThis[Symbol.for('language.test.query')] = () => {
    reading.resolve();
    return snapshot.promise;
  };
  const saving = settings.setLanguage('zh-TW');
  await settings.setLanguage('zh-CN');
  assert.equal(language(), 'en');
  assert.equal(settings.preferences.language, 'en');
  mutation.resolve(returned({ kind: 'committed', revision: 11 }));
  await reading.promise;
  assert.equal(t('newTask'), 'New task');
  assert.equal(settings.preferences.revision, 10);
  snapshot.resolve({ revision: 11, language: 'zh-TW', resolvedLanguage: 'zh-TW' });
  await saving;
  assert.equal(t('newTask'), '新任務');
  assert.equal(settings.modelQuery.placeholder, '搜尋模型');
  assert.equal(settings.preferences.language, 'zh-TW');
  assert.deepEqual(mutations, [
    [
      'settings',
      'updateAssistantPreferences',
      { expectedRevision: 10, mutation: { kind: 'language', preference: 'zh-TW' } },
      undefined,
    ],
  ]);
  assert.equal(settings.busy, null);
  assert.equal(settings.error, null);
});

test('conflict refreshes the actual Host value without replaying the mutation', async () => {
  const { settings, reports } = setup({ revision: 20, language: 'en', resolvedLanguage: 'en' });
  await settings.loadPreferences();
  const mutations = [];
  globalThis[Symbol.for('language.test.mutate')] = (...args) => {
    mutations.push(args);
    return returned({ kind: 'revision_conflict', expectedRevision: 20, actualRevision: 21 });
  };
  globalThis[Symbol.for('language.test.query')] = async () => ({
    revision: 21,
    language: 'auto',
    resolvedLanguage: 'en',
  });
  await settings.setLanguage('zh-CN');
  assert.deepEqual(settings.preferences, {
    revision: 21,
    language: 'auto',
    resolvedLanguage: 'en',
  });
  assert.equal(t('newTask'), 'New task');
  assert.deepEqual(reports, [
    'Settings: Preferences changed elsewhere. The current language was reloaded; choose again to save.',
  ]);
  assert.deepEqual(
    mutations.map((args) => args[2]),
    [{ expectedRevision: 20, mutation: { kind: 'language', preference: 'zh-CN' } }],
  );
});

for (const [name, response, error] of [
  ['rejected', returned({ kind: 'rejected' }), 'Settings: The Host rejected the language change.'],
  [
    'unknown receipt',
    { receipt: { kind: 'unknown' } },
    'Settings: settings.updateAssistantPreferences was not recorded as returned: {"kind":"unknown"}',
  ],
  ['failed readback', returned({ kind: 'committed', revision: 31 }), 'Settings: read unavailable'],
]) {
  test(`${name} preserves the confirmed language and reports failure`, async () => {
    const { settings, reports } = setup({ revision: 30, language: 'en', resolvedLanguage: 'en' });
    await settings.loadPreferences();
    const mutations = [];
    globalThis[Symbol.for('language.test.mutate')] = (...args) => {
      mutations.push(args);
      return response;
    };
    globalThis[Symbol.for('language.test.query')] = () => {
      throw new Error('read unavailable');
    };
    await settings.setLanguage('auto');
    assert.equal(language(), 'en');
    assert.deepEqual(settings.preferences, {
      revision: 30,
      language: 'en',
      resolvedLanguage: 'en',
    });
    assert.deepEqual(reports, [error]);
    assert.deepEqual(
      mutations.map((args) => args[2]),
      [{ expectedRevision: 30, mutation: { kind: 'language', preference: 'auto' } }],
    );
  });
}

test('late read cannot roll back a newer Host snapshot', async () => {
  const { settings } = setup({ revision: 40, language: 'en', resolvedLanguage: 'en' });
  await settings.loadPreferences();
  const old = deferred();
  globalThis[Symbol.for('language.test.query')] = () => old.promise;
  const pending = settings.loadPreferences();
  globalThis[Symbol.for('language.test.query')] = async () => ({
    revision: 42,
    language: 'auto',
    resolvedLanguage: 'zh-CN',
  });
  await settings.loadPreferences();
  old.resolve({ revision: 41, language: 'en', resolvedLanguage: 'en' });
  await pending;
  assert.deepEqual(settings.preferences, {
    revision: 42,
    language: 'auto',
    resolvedLanguage: 'zh-CN',
  });
  assert.equal(t('newTask'), '新任务');
});

test('the production startup reads Host language before starting conversation loads', async () => {
  const { settings, requests } = setup({
    revision: 50,
    language: 'auto',
    resolvedLanguage: 'zh-TW',
  });
  const labels = [];
  const app = {
    settings,
    rootFocus: { focus() {} },
    composer: { loadModel: () => labels.push(t('newTask')) },
    directories: { loadRoots() {} },
    catalog: { run() {} },
  };
  await MakaDesktop.prototype.start.call(app, { bind_keys() {}, spawn() {} });
  assert.deepEqual(labels, ['新任務']);
  assert.deepEqual(requests, [{ endpoint: 'settings', method: 'assistantPreferences', input: {} }]);
});

test('reopening Settings reads another client’s language without local storage', async () => {
  const { settings } = setup({ revision: 60, language: 'zh-TW', resolvedLanguage: 'zh-TW' });
  await settings.load();
  const finished = deferred();
  const { read } = setup({ revision: 61, language: 'en', resolvedLanguage: 'en' });
  globalThis[Symbol.for('language.test.query')] = read;
  settings.hooks.changed = () => {
    if (!settings.loading && settings.preferences?.revision === 61) finished.resolve();
  };
  settings.show();
  await finished.promise;
  assert.equal(settings.open, true);
  assert.equal(settings.preferences.language, 'en');
  assert.equal(settings.modelQuery.placeholder, 'Find a model');
  assert.equal(t('newTask'), 'New task');
});

// Native element builders record the callback/disabled state, not pixels or
// layout. All Settings rendering and event wiring remains production code.
function elements() {
  const buttons = new Map();
  const labels = [];
  globalThis[Symbol.for('language.test.element')] = (id) => {
    const value = { disabled: false, click: null };
    let element;
    element = new Proxy(value, {
      get(target, name) {
        if (name === 'when') return (condition, render) => (condition ? render(element) : element);
        if (name === 'child') {
          return (child) => {
            if (typeof child === 'string') labels.push(child);
            return element;
          };
        }
        if (name === 'disabled') {
          return (disabled) => {
            target.disabled = disabled;
            return element;
          };
        }
        if (name === 'on_click') {
          return (click) => {
            target.click = click;
            return element;
          };
        }
        return () => element;
      },
    });
    if (typeof id === 'string') buttons.set(id, value);
    return element;
  };
  return { buttons, labels };
}

test('the General language button uses Host CAS; inherited default is not saved auto', async () => {
  const { settings } = setup({ revision: 70, language: null, resolvedLanguage: 'zh-TW' });
  const { buttons, labels } = elements();
  const cx = { theme: () => ({ is_dark: false }) };
  settingsPage(settings, cx);
  assert.equal(buttons.get('language-auto').disabled, true);
  await settings.load();
  settingsPage(settings, cx);
  assert.equal(buttons.get('language-auto').disabled, false);
  assert.deepEqual(
    labels.filter((label) => label.endsWith('\nHost 預設：繁體中文')),
    ['儲存到目前連線的 Host，用於介面與新任務。已受理的任務保留原語言。\nHost 預設：繁體中文'],
  );
  const mutations = [];
  globalThis[Symbol.for('language.test.mutate')] = (...args) => {
    mutations.push(args);
    return returned({ kind: 'committed', revision: 71 });
  };
  globalThis[Symbol.for('language.test.query')] = async () => ({
    revision: 71,
    language: 'auto',
    resolvedLanguage: 'zh-CN',
  });
  await buttons.get('language-auto').click();
  assert.deepEqual(
    mutations.map((args) => args[2]),
    [{ expectedRevision: 70, mutation: { kind: 'language', preference: 'auto' } }],
  );
  assert.equal(settings.preferences.language, 'auto');
  assert.equal(t('newTask'), '新任务');
});
