const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');

const rootDir = process.cwd();

test('web and worker boot cleanly in direct node mode', (t) => {
  const dataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'mastermind-startup-'));
  const env = {
    ...process.env,
    DATA_DIR: dataDir,
    DATABASE_URL: 'memory://smoke',
    SESSION_SECRET: 'smoke-test-secret',
    BOOTSTRAP_OWNER_EMAIL: 'owner@local',
    BOOTSTRAP_OWNER_PASSWORD: 'owner',
    MASTERMIND_DISABLE_LISTEN: '1',
    NODE_ENV: 'test',
    WORKER_TICK_MS: '100',
    WORKER_RUN_ONCE: '1'
  };

  t.after(() => {
    fs.rmSync(dataDir, { recursive: true, force: true });
  });

  const web = spawnSync(process.execPath, ['web/src/index.js'], {
    cwd: rootDir,
    env,
    encoding: 'utf8'
  });
  const worker = spawnSync(process.execPath, ['worker/src/worker.js'], {
    cwd: rootDir,
    env,
    encoding: 'utf8'
  });

  assert.equal(web.status, 0, web.stderr || web.stdout);
  assert.equal(worker.status, 0, worker.stderr || worker.stdout);
});

test('memory-backed flow supports project creation, email sorting, and draft generation', async () => {
  const [{ createMemoryPool }, { applyRulesToEmail }, { buildPCOBody }] = await Promise.all([
    import('../web/src/lib/memory-db.js'),
    import('../web/src/lib/email-rules.js'),
    import('../web/src/lib/utils.js')
  ]);

  const pool = createMemoryPool();

  const ownerInsert = await pool.query(
    "insert into users(email, display_name, role) values ($1,'Owner','owner') returning id",
    ['owner@local']
  );
  const ownerId = ownerInsert.rows[0].id;
  await pool.query(
    "insert into identities(user_id, provider, email, password_hash) values ($1,'local',$2,$3)",
    [ownerId, 'owner@local', 'hash']
  );

  const projectInsert = await pool.query(
    `insert into projects(created_by_user_id,name,job_number,role_mode,gc_name,city,state,keywords)
     values ($1,$2,$3,$4,$5,$6,$7,$8)
     returning id`,
    [ownerId, 'Smoke Test Project', '0222600001', 'ec', 'Example GC', 'Durham', 'NC', 'smoke']
  );
  const projectId = projectInsert.rows[0].id;
  await pool.query(
    `insert into project_members(project_id,user_id,project_role) values ($1,$2,'owner')
     on conflict do nothing`,
    [projectId, ownerId]
  );

  await pool.query(
    `insert into email_rules(created_by_user_id, project_id, match_type, match_value, priority)
     values ($1,$2,$3,$4,$5)
     returning id`,
    [ownerId, projectId, 'subject_contains', '0222600001', 10]
  );

  const emailInsert = await pool.query(
    `insert into ingested_emails(created_by_user_id, source, from_addr, to_addr, cc_addr, subject, date, body_text, body_html, has_attachments, raw_path, sha256, status)
     values ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,'unsorted')
     returning *`,
    [
      ownerId,
      'upload',
      'pm@example.com',
      'team@example.com',
      '',
      'RE: 0222600001 coordination',
      new Date('2026-03-01T12:00:00.000Z'),
      'Need pricing and schedule impact.',
      '',
      false,
      '/tmp/sample.eml',
      'abc123'
    ]
  );
  const email = emailInsert.rows[0];

  const rules = (await pool.query(
    `select * from email_rules where enabled=true order by priority asc, created_at asc`
  )).rows;
  const match = await applyRulesToEmail(email, rules);
  assert.deepEqual(
    { projectId: match.projectId, confidence: match.confidence },
    { projectId, confidence: 0.9 }
  );

  await pool.query(
    `update ingested_emails set project_id=$1, status=$2, confidence=$3 where id=$4`,
    [projectId, 'assigned', match.confidence, email.id]
  );

  const assignedEmails = await pool.query(
    `select id, from_addr, subject, date, source
     from ingested_emails
     where project_id=$1
     order by date desc nulls last, created_at desc
     limit 300`,
    [projectId]
  );
  assert.equal(assignedEmails.rows.length, 1);
  assert.equal(assignedEmails.rows[0].subject, 'RE: 0222600001 coordination');

  const body = buildPCOBody(email, { name: 'Smoke Test Project', job_number: '0222600001' });
  const draftInsert = await pool.query(
    `insert into pco_drafts(created_by_user_id, project_id, source_email_id, title, body)
     values ($1,$2,$3,$4,$5) returning id`,
    [ownerId, projectId, email.id, 'PCO: RE: 0222600001 coordination', body]
  );

  const draft = await pool.query('select * from pco_drafts where id=$1', [draftInsert.rows[0].id]);
  assert.equal(draft.rows[0].source_email_id, email.id);
  assert.match(draft.rows[0].body, /Need pricing and schedule impact\./);
});
