const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');

test('background imports account run history module', () => {
  const source = fs.readFileSync('background.js', 'utf8');
  assert.match(source, /background\/account-run-history\.js/);
});

test('account run history module exposes a factory', () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};

  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  assert.equal(typeof api?.createAccountRunHistoryHelpers, 'function');
});

test('account run history helper upgrades old records, keeps stopped items and stores normalized failed snapshot records', async () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  let storedHistory = [
    { email: 'old@example.com', password: 'old-pass', status: 'success', recordedAt: '2026-04-17T00:00:00.000Z' },
    { email: 'stop@example.com', password: 'stop-pass', status: 'stopped', recordedAt: '2026-04-17T00:10:00.000Z' },
  ];
  let fetchCalled = false;
  global.fetch = async () => {
    fetchCalled = true;
    throw new Error('should not call fetch');
  };

  const helpers = api.createAccountRunHistoryHelpers({
    ACCOUNT_RUN_HISTORY_STORAGE_KEY: 'accountRunHistory',
    addLog: async () => {},
    buildLocalHelperEndpoint: (baseUrl, path) => `${baseUrl}${path}`,
    chrome: {
      storage: {
        local: {
          get: async () => ({ accountRunHistory: storedHistory }),
          set: async (payload) => {
            storedHistory = payload.accountRunHistory;
          },
        },
      },
    },
    getErrorMessage: (error) => error?.message || String(error || ''),
    getState: async () => ({
      email: ' latest@example.com ',
      password: ' secret ',
      autoRunning: true,
      autoRunCurrentRun: 2,
      autoRunTotalRuns: 10,
      autoRunAttemptRun: 3,
      accountRunHistoryTextEnabled: false,
      accountRunHistoryHelperBaseUrl: 'http://127.0.0.1:17373',
    }),
    normalizeAccountRunHistoryHelperBaseUrl: (value) => String(value || '').trim(),
  });

  const record = helpers.buildAccountRunHistoryRecord(
    {
      email: ' latest@example.com ',
      password: ' secret ',
      autoRunning: true,
      autoRunCurrentRun: 2,
      autoRunTotalRuns: 10,
      autoRunAttemptRun: 3,
    },
    'step8_failed',
    '步骤 8：认证页进入了手机号页面，当前不是 OAuth 同意页，无法继续自动授权。'
  );
  assert.deepStrictEqual(record, {
    recordId: 'latest@example.com',
    accountIdentifierType: 'email',
    accountIdentifier: 'latest@example.com',
    email: 'latest@example.com',
    phoneNumber: '',
    password: 'secret',
    finalStatus: 'failed',
    finishedAt: record.finishedAt,
    retryCount: 2,
    failureLabel: '出现手机号验证',
    failureDetail: '步骤 8：认证页进入了手机号页面，当前不是 OAuth 同意页，无法继续自动授权。',
    failedStep: 8,
    source: 'auto',
    autoRunContext: {
      currentRun: 2,
      totalRuns: 10,
      attemptRun: 3,
    },
    plusModeEnabled: false,
    contributionMode: false,
  });

  const appended = await helpers.appendAccountRunRecord('step8_failed', null, '步骤 8：认证页进入了手机号页面，当前不是 OAuth 同意页，无法继续自动授权。');
  assert.equal(appended.email, 'latest@example.com');
  assert.equal(appended.finalStatus, 'failed');
  assert.equal(appended.failureLabel, '出现手机号验证');
  assert.equal(storedHistory.length, 3, '旧的 stopped 记录应在新结构中保留');
  assert.equal(storedHistory.some((item) => item.email === 'stop@example.com' && item.finalStatus === 'stopped'), true);
  assert.equal(storedHistory.some((item) => item.email === 'latest@example.com' && item.retryCount === 2), true);
  assert.equal(storedHistory.some((item) => item.email === 'old@example.com'), true);
  assert.equal(fetchCalled, true);
  assert.equal(helpers.shouldAppendAccountRunTextFile({ accountRunHistoryTextEnabled: false, accountRunHistoryHelperBaseUrl: 'http://127.0.0.1:17373' }), true);
  assert.equal(helpers.shouldAppendAccountRunTextFile({ accountRunHistoryTextEnabled: true, accountRunHistoryHelperBaseUrl: 'http://127.0.0.1:17373' }), true);
  const stoppedRecord = helpers.buildAccountRunHistoryRecord(
    { email: 'a@b.com', password: 'x' },
    'step7_stopped',
    '步骤 7 已被用户停止'
  );
  assert.equal(stoppedRecord.recordId, 'a@b.com');
  assert.equal(stoppedRecord.email, 'a@b.com');
  assert.equal(stoppedRecord.password, 'x');
  assert.equal(stoppedRecord.finalStatus, 'stopped');
  assert.equal(stoppedRecord.retryCount, 0);
  assert.equal(stoppedRecord.failureLabel, '步骤 7 停止');
  assert.equal(stoppedRecord.failureDetail, '步骤 7 已被用户停止');
  assert.equal(stoppedRecord.failedStep, 7);
  assert.equal(stoppedRecord.source, 'manual');
  assert.equal(stoppedRecord.autoRunContext, null);
  assert.ok(stoppedRecord.finishedAt);

  const genericStoppedRecord = helpers.buildAccountRunHistoryRecord({ email: 'stop@b.com', password: 'y' }, 'stopped', 'stop');
  assert.equal(genericStoppedRecord.failureLabel, '流程已停止');
  assert.equal(genericStoppedRecord.failedStep, null);

  const normalizedStoppedRecord = helpers.normalizeAccountRunHistoryRecord({
    recordId: 'legacy-stop@example.com',
    email: 'legacy-stop@example.com',
    password: 'secret',
    finalStatus: 'stopped',
    finishedAt: '2026-04-17T00:12:00.000Z',
    retryCount: 0,
    failureLabel: '流程已停止',
    failureDetail: '步骤 7 已被用户停止。',
    failedStep: 7,
    source: 'manual',
    autoRunContext: null,
  });
  assert.equal(normalizedStoppedRecord.failureLabel, '步骤 7 停止');
  assert.equal(normalizedStoppedRecord.failedStep, 7);
});

test('account run history helper accepts phone-only records without forcing email or password', () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  const helpers = api.createAccountRunHistoryHelpers({
    chrome: { storage: { local: { get: async () => ({}), set: async () => {} } } },
    getState: async () => ({}),
    normalizeAccountRunHistoryHelperBaseUrl: (value) => String(value || '').trim(),
  });

  const record = helpers.buildAccountRunHistoryRecord({
    accountIdentifierType: 'phone',
    accountIdentifier: '+6612345',
    signupPhoneNumber: '+6612345',
    password: '',
  }, 'success');

  assert.deepStrictEqual(record, {
    recordId: 'phone:+6612345',
    accountIdentifierType: 'phone',
    accountIdentifier: '+6612345',
    email: '',
    phoneNumber: '+6612345',
    password: '',
    finalStatus: 'success',
    finishedAt: record.finishedAt,
    retryCount: 0,
    failureLabel: '流程完成',
    failureDetail: '',
    failedStep: null,
    source: 'manual',
    autoRunContext: null,
    plusModeEnabled: false,
    contributionMode: false,
  });

  const normalized = helpers.normalizeAccountRunHistoryRecord({
    recordId: 'phone:+6612345',
    accountIdentifierType: 'phone',
    accountIdentifier: '+6612345',
    phoneNumber: '+6612345',
    finalStatus: 'failed',
    failureDetail: '步骤 8：手机号验证码超时。',
  });

  assert.equal(normalized.recordId, 'phone:+6612345');
  assert.equal(normalized.accountIdentifierType, 'phone');
  assert.equal(normalized.accountIdentifier, '+6612345');
  assert.equal(normalized.email, '');
  assert.equal(normalized.phoneNumber, '+6612345');
  assert.equal(normalized.password, '');
  assert.equal(normalized.finalStatus, 'failed');
});

test('account run history does not turn prerequisite guidance into a fake step 2 failure', () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  const helpers = api.createAccountRunHistoryHelpers({
    chrome: { storage: { local: { get: async () => ({}), set: async () => {} } } },
    getState: async () => ({}),
    normalizeAccountRunHistoryHelperBaseUrl: (value) => String(value || '').trim(),
  });

  const genericFailedRecord = helpers.buildAccountRunHistoryRecord({
    email: 'late@example.com',
    password: 'secret',
    autoRunning: true,
    autoRunCurrentRun: 1,
    autoRunTotalRuns: 3,
    autoRunAttemptRun: 2,
  }, 'failed', '缺少登录账号：请先完成步骤 2，或在侧栏填写账号后再执行当前步骤。');

  assert.equal(genericFailedRecord.failedStep, null);
  assert.equal(genericFailedRecord.failureLabel, '流程失败');

  const explicitFailedRecord = helpers.buildAccountRunHistoryRecord({
    email: 'late@example.com',
    password: 'secret',
    autoRunning: true,
    autoRunCurrentRun: 1,
    autoRunTotalRuns: 3,
    autoRunAttemptRun: 2,
  }, 'step10_failed', '缺少登录账号：请先完成步骤 2，或在侧栏填写账号后再执行当前步骤。');

  assert.equal(explicitFailedRecord.failedStep, 10);
  assert.equal(explicitFailedRecord.failureLabel, '步骤 10 失败');

  const migratedOldRecord = helpers.normalizeAccountRunHistoryRecord({
    email: 'old@example.com',
    password: 'secret',
    finalStatus: 'failed',
    failureLabel: '步骤 2 失败',
    failureDetail: '缺少登录账号：请先完成步骤 2，或在侧栏填写账号后再执行当前步骤。',
    failedStep: 2,
  });

  assert.equal(migratedOldRecord.failedStep, null);
  assert.equal(migratedOldRecord.failureLabel, '流程失败');
});

test('account run history merges email and phone identities from the same run', async () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  let storedHistory = [
    {
      recordId: 'phone:+447799342687',
      accountIdentifierType: 'phone',
      accountIdentifier: '+447799342687',
      phoneNumber: '+44 7799 342687',
      email: '',
      password: '',
      finalStatus: 'stopped',
      finishedAt: '2026-04-17T04:30:00.000Z',
      failureDetail: '步骤 2 已使用手机号，流程尚未完成。',
    },
    {
      recordId: 'tmp@example.com',
      accountIdentifierType: 'email',
      accountIdentifier: 'tmp@example.com',
      email: 'tmp@example.com',
      phoneNumber: '',
      password: 'old',
      finalStatus: 'stopped',
      finishedAt: '2026-04-17T04:31:00.000Z',
      failureDetail: '步骤 2 已使用邮箱，流程尚未完成。',
    },
  ];

  const helpers = api.createAccountRunHistoryHelpers({
    chrome: {
      storage: {
        local: {
          get: async () => ({ accountRunHistory: storedHistory }),
          set: async (payload) => {
            storedHistory = payload.accountRunHistory;
          },
        },
      },
    },
    getState: async () => ({}),
    normalizeAccountRunHistoryHelperBaseUrl: () => '',
  });

  const failedRecord = helpers.buildAccountRunHistoryRecord({
    accountIdentifierType: 'email',
    accountIdentifier: 'tmp@example.com',
    email: 'tmp@example.com',
    password: 'secret',
    currentPhoneActivation: {
      activationId: 'a1',
      phoneNumber: '+44 7799 342687',
    },
  }, 'step9_failed', '步骤 9：手机号验证失败。');
  assert.equal(failedRecord.accountIdentifierType, 'email');
  assert.equal(failedRecord.accountIdentifier, 'tmp@example.com');
  assert.equal(failedRecord.phoneNumber, '+44 7799 342687');

  const successRecord = await helpers.appendAccountRunRecord('success', {
    accountIdentifierType: 'email',
    accountIdentifier: 'tmp@example.com',
    email: 'tmp@example.com',
    phoneNumber: '447799342687',
    password: 'secret',
    accountRunHistoryHelperBaseUrl: '',
  });

  assert.equal(successRecord.recordId, 'tmp@example.com');
  assert.equal(successRecord.email, 'tmp@example.com');
  assert.equal(successRecord.phoneNumber, '447799342687');
  assert.equal(storedHistory.length, 1);
  assert.equal(storedHistory[0].recordId, 'tmp@example.com');
  assert.equal(storedHistory[0].finalStatus, 'success');
});

test('account run history keeps phone as primary identity when phone signup later binds email', async () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  let storedHistory = [{
    recordId: 'phone:+447700900123',
    accountIdentifierType: 'phone',
    accountIdentifier: '+447700900123',
    phoneNumber: '+447700900123',
    email: '',
    finalStatus: 'stopped',
    finishedAt: '2026-04-17T04:31:00.000Z',
    failureDetail: '步骤 2 已使用手机号，流程尚未完成。',
  }];

  const helpers = api.createAccountRunHistoryHelpers({
    chrome: {
      storage: {
        local: {
          get: async () => ({ accountRunHistory: storedHistory }),
          set: async (payload) => {
            storedHistory = payload.accountRunHistory;
          },
        },
      },
    },
    getState: async () => ({}),
    normalizeAccountRunHistoryHelperBaseUrl: () => '',
  });

  const record = await helpers.appendAccountRunRecord('success', {
    accountIdentifierType: 'phone',
    accountIdentifier: '+447700900123',
    signupPhoneNumber: '+447700900123',
    email: 'bound@example.com',
    password: 'secret',
    accountRunHistoryHelperBaseUrl: '',
  });

  assert.equal(record.recordId, 'phone:+447700900123');
  assert.equal(record.accountIdentifierType, 'phone');
  assert.equal(record.accountIdentifier, '+447700900123');
  assert.equal(record.email, 'bound@example.com');
  assert.equal(record.phoneNumber, '+447700900123');
  assert.equal(storedHistory.length, 1);
  assert.equal(storedHistory[0].recordId, 'phone:+447700900123');
  assert.equal(storedHistory[0].finalStatus, 'success');
});

test('account run history records preserve Plus and contribution mode flags', () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  const helpers = api.createAccountRunHistoryHelpers({
    chrome: { storage: { local: { get: async () => ({}), set: async () => {} } } },
    getState: async () => ({}),
    normalizeAccountRunHistoryHelperBaseUrl: (value) => String(value || '').trim(),
  });

  const record = helpers.buildAccountRunHistoryRecord({
    email: 'plus@example.com',
    password: 'secret',
    plusModeEnabled: true,
    contributionMode: true,
  }, 'success');

  assert.equal(record.plusModeEnabled, true);
  assert.equal(record.contributionMode, true);

  const normalized = helpers.normalizeAccountRunHistoryRecord({
    email: 'plus@example.com',
    password: 'secret',
    finalStatus: 'success',
    plusModeEnabled: true,
    contributionMode: true,
  });

  assert.equal(normalized.plusModeEnabled, true);
  assert.equal(normalized.contributionMode, true);
});

test('account run history helper clears persisted records and syncs full snapshot payload to local helper', async () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  let storedHistory = [{
    recordId: 'user@example.com',
    email: 'user@example.com',
    password: 'secret',
    finalStatus: 'failed',
    finishedAt: '2026-04-17T01:00:00.000Z',
    retryCount: 1,
    failureLabel: '步骤 6 失败',
    failureDetail: '步骤 6：判断失败后已重试 2 次，仍未成功。',
    failedStep: 6,
    source: 'auto',
    autoRunContext: {
      currentRun: 1,
      totalRuns: 5,
      attemptRun: 2,
    },
  }];
  const fetchCalls = [];
  global.fetch = async (url, options = {}) => {
    fetchCalls.push({
      url,
      options,
    });
    return {
      ok: true,
      json: async () => ({
        ok: true,
        filePath: 'C:/tmp/account-run-history.json',
      }),
    };
  };

  const logs = [];
  const helpers = api.createAccountRunHistoryHelpers({
    ACCOUNT_RUN_HISTORY_STORAGE_KEY: 'accountRunHistory',
    addLog: async (message, level) => {
      logs.push({ message, level });
    },
    buildLocalHelperEndpoint: (baseUrl, path) => `${baseUrl}${path}`,
    chrome: {
      storage: {
        local: {
          get: async () => ({ accountRunHistory: storedHistory }),
          set: async (payload) => {
            storedHistory = payload.accountRunHistory;
          },
        },
      },
    },
    getErrorMessage: (error) => error?.message || String(error || ''),
    getState: async () => ({
      accountRunHistoryTextEnabled: true,
      accountRunHistoryHelperBaseUrl: 'http://127.0.0.1:17373',
    }),
    normalizeAccountRunHistoryHelperBaseUrl: (value) => String(value || '').trim(),
  });

  const payload = helpers.buildAccountRunHistorySnapshotPayload(storedHistory);
  assert.deepStrictEqual(payload.summary, {
    total: 1,
    success: 0,
    failed: 1,
    stopped: 0,
    retryTotal: 1,
  });

  const clearResult = await helpers.clearAccountRunHistory();
  assert.deepStrictEqual(clearResult, { clearedCount: 1 });
  assert.deepStrictEqual(storedHistory, []);
  assert.equal(fetchCalls.length, 1);
  assert.equal(fetchCalls[0].url, 'http://127.0.0.1:17373/sync-account-run-records');
  assert.deepStrictEqual(JSON.parse(fetchCalls[0].options.body), {
    generatedAt: JSON.parse(fetchCalls[0].options.body).generatedAt,
    summary: {
      total: 0,
      success: 0,
      failed: 0,
      stopped: 0,
      retryTotal: 0,
    },
    records: [],
  });
  assert.equal(logs[0].message, '账号记录快照已同步到本地：C:/tmp/account-run-history.json');
});

test('account run history helper deletes selected records and syncs remaining snapshot payload', async () => {
  const source = fs.readFileSync('background/account-run-history.js', 'utf8');
  const globalScope = {};
  const api = new Function('self', `${source}; return self.MultiPageBackgroundAccountRunHistory;`)(globalScope);

  let storedHistory = [
    {
      recordId: 'keep@example.com',
      email: 'keep@example.com',
      password: 'secret',
      finalStatus: 'success',
      finishedAt: '2026-04-17T01:10:00.000Z',
      retryCount: 0,
      failureLabel: '流程完成',
      failureDetail: '',
      failedStep: null,
      source: 'manual',
      autoRunContext: null,
    },
    {
      recordId: 'remove@example.com',
      email: 'remove@example.com',
      password: 'secret',
      finalStatus: 'failed',
      finishedAt: '2026-04-17T01:00:00.000Z',
      retryCount: 2,
      failureLabel: '步骤 8 失败',
      failureDetail: '步骤 8：认证页异常',
      failedStep: 8,
      source: 'auto',
      autoRunContext: {
        currentRun: 1,
        totalRuns: 5,
        attemptRun: 3,
      },
    },
  ];
  const fetchCalls = [];
  global.fetch = async (url, options = {}) => {
    fetchCalls.push({
      url,
      options,
    });
    return {
      ok: true,
      json: async () => ({
        ok: true,
        filePath: 'C:/tmp/account-run-history.json',
      }),
    };
  };

  const logs = [];
  const helpers = api.createAccountRunHistoryHelpers({
    ACCOUNT_RUN_HISTORY_STORAGE_KEY: 'accountRunHistory',
    addLog: async (message, level) => {
      logs.push({ message, level });
    },
    buildLocalHelperEndpoint: (baseUrl, path) => `${baseUrl}${path}`,
    chrome: {
      storage: {
        local: {
          get: async () => ({ accountRunHistory: storedHistory }),
          set: async (payload) => {
            storedHistory = payload.accountRunHistory;
          },
        },
      },
    },
    getErrorMessage: (error) => error?.message || String(error || ''),
    getState: async () => ({
      accountRunHistoryTextEnabled: true,
      accountRunHistoryHelperBaseUrl: 'http://127.0.0.1:17373',
    }),
    normalizeAccountRunHistoryHelperBaseUrl: (value) => String(value || '').trim(),
  });

  const result = await helpers.deleteAccountRunHistoryRecords(['remove@example.com']);
  assert.deepStrictEqual(result, {
    deletedCount: 1,
    remainingCount: 1,
  });
  assert.equal(storedHistory.length, 1);
  assert.equal(storedHistory[0].email, 'keep@example.com');
  assert.equal(fetchCalls.length, 1);
  assert.equal(fetchCalls[0].url, 'http://127.0.0.1:17373/sync-account-run-records');
  assert.deepStrictEqual(JSON.parse(fetchCalls[0].options.body), {
    generatedAt: JSON.parse(fetchCalls[0].options.body).generatedAt,
    summary: {
      total: 1,
      success: 1,
      failed: 0,
      stopped: 0,
      retryTotal: 0,
    },
    records: storedHistory,
  });
  assert.equal(logs[0].message, '账号记录快照已同步到本地：C:/tmp/account-run-history.json');
});
