import { strict as assert } from 'node:assert';
import { describe, it } from 'node:test';
import { ACCOUNT_SIDES } from '@pig/core';
import type { Database } from '@pig/db';
import type { Principal } from '../src/lib/auth';
import { executeMutation } from '../src/lib/mutation';
import { createImportCommitMutationDefinition } from '../src/routes/imports';
import { convertImportRow, findDuplicateImportKeys } from '../src/services/imports';
import { parseCsv, parseWorksheetXml } from '../src/services/tabular-import';

const principal: Principal = {
  userId: '00000000-0000-4000-8000-000000000001',
  email: 'admin@example.com',
  name: 'Import admin',
  isPlatformAdmin: false,
  teams: [{ team: 'demand', role: 'admin' }],
  via: 'jwt',
  scopes: ['read', 'write'],
};

describe('untrusted tabular parsing', () => {
  it('keeps multiline CSV and formula-like cells as inert text', () => {
    const parsed = parseCsv('external_id,name\n1,"Acme\nCompute"\n2,"=WEBSERVICE(""https://example.test"")"');
    assert.deepEqual(parsed.headers, ['external_id', 'name']);
    assert.equal(parsed.rows[0]?.[1], 'Acme\nCompute');
    assert.equal(parsed.rows[1]?.[1], '=WEBSERVICE("https://example.test")');
    assert.match(parsed.warnings.join(' '), /inert text/);
  });

  it('does not execute XLSX formulas or follow formula URLs', () => {
    const parsed = parseWorksheetXml(
      '<worksheet><sheetData><row>' +
      '<c r="A1" t="inlineStr"><is><t>external_id</t></is></c>' +
      '<c r="B1" t="inlineStr"><is><t>score</t></is></c>' +
      '</row><row><c r="A2"><v>1</v></c>' +
      '<c r="B2"><f>WEBSERVICE(&quot;https://example.test&quot;)</f><v>7</v></c>' +
      '</row></sheetData></worksheet>',
    );
    assert.deepEqual(parsed.rows, [['1', '7']]);
    assert.match(parsed.warnings.join(' '), /not executed/);
  });
});

describe('import row decisions', () => {
  it('rejects duplicate user-selected source identities', () => {
    assert.deepEqual([...findDuplicateImportKeys(['vendor-1', 'vendor-2', 'vendor-1'])], ['vendor-1']);
  });

  it('validates ontology values from core rather than accepting invented sides', () => {
    const converted = convertImportRow(
      'account',
      ['external_id', 'name', 'side'],
      ['vendor-1', 'Acme', 'marketplace'],
      { name: 'name', side: 'side' },
      true,
    );
    assert.equal(converted.values.name, 'Acme');
    const message = converted.errors[0]?.message ?? '';
    assert.match(message, /must be one of/);
    for (const side of ACCOUNT_SIDES) assert.ok(message.includes(side));
  });
});

describe('import commit mutation', () => {
  it('commits imported records and their audit evidence in one transaction', async () => {
    const events: string[] = [];
    const tx = {
      insert: () => ({ values: async () => events.push('activity') }),
    };
    const db = {
      transaction: async (work: (transaction: unknown) => Promise<unknown>) => {
        events.push('begin');
        const result = await work(tx);
        events.push('commit');
        return result;
      },
    } as unknown as Database;
    const definition = createImportCommitMutationDefinition((transaction) => {
      assert.equal(transaction, tx);
      return {
        commit: async () => {
          events.push('records-and-identities');
          return { created: 1, updated: 0, total: 1 };
        },
      };
    });

    await executeMutation(db, principal, async () => ({
      entity: 'account',
      sourceName: 'accounts.csv',
      headers: ['external_id', 'name', 'side'],
      rows: [['vendor-1', 'Acme', 'demand']],
      mapping: { name: 'name', side: 'side' },
      keySourceColumn: 'external_id',
      previewDigest: 'a'.repeat(64),
    }), definition);

    assert.deepEqual(events, ['begin', 'records-and-identities', 'activity', 'commit']);
  });
});
