import { mkdtempSync, rmSync, existsSync, readFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { resolve, join } from 'node:path';
import { spawnSync } from 'node:child_process';

const args = new Set(process.argv.slice(2));
const checkOnly = args.has('--check');
const repoRoot = resolve(new URL('../..', import.meta.url).pathname);
const matrixCli = resolve(repoRoot, 'packages', 'cli', 'dist', 'bin', 'matrix.js');

function envString(...names) {
  for (const name of names) {
    const value = process.env[name];
    if (typeof value === 'string' && value.trim()) return value.trim();
  }
  return undefined;
}

function run(command, commandArgs, options = {}) {
  const result = spawnSync(command, commandArgs, {
    cwd: options.cwd ?? repoRoot,
    stdio: options.stdio ?? 'pipe',
    env: process.env,
    encoding: 'utf8',
  });
  if (result.error) throw result.error;
  if (result.status !== 0) {
    throw new Error(`${command} ${commandArgs.join(' ')} failed with exit ${result.status}\n${result.stderr}${result.stdout}`);
  }
  return result;
}

function resolveConfig() {
  const key = envString('MATRIX_API_KEY', 'HIVECAST_API_KEY', 'HIVECAST_TEST_KEY');
  const cloud = envString('MATRIX_CLOUD', 'HIVECAST_CLOUD', 'HIVECAST_TEST_CLOUD');
  const space = envString('MATRIX_SPACE', 'HIVECAST_SPACE', 'HIVECAST_TEST_SPACE');
  const provided = [key, cloud, space].filter(Boolean).length;
  if (provided > 0 && provided < 3) {
    throw new Error('Provide MATRIX_API_KEY, MATRIX_CLOUD, and MATRIX_SPACE together');
  }
  return key && cloud && space
    ? { key, cloud: cloud.replace(/\/+$/g, ''), space }
    : null;
}

async function validateHiveCastKey(config) {
  const response = await fetch(`${config.cloud}/api/install/key-info`, {
    method: 'POST',
    headers: {
      authorization: `Bearer ${config.key}`,
      'content-type': 'application/json',
    },
    body: JSON.stringify({ space: config.space }),
  });
  const text = await response.text();
  if (!response.ok) {
    throw new Error(`HiveCast key validation failed (${response.status}): ${text}`);
  }
  const body = text.trim() ? JSON.parse(text) : {};
  if (body?.ok !== true) {
    throw new Error(`HiveCast key validation did not return ok:true: ${text}`);
  }
  return {
    keyId: body.key?.id ?? body.id ?? null,
    fingerprint: body.key?.fingerprint ?? body.fingerprint ?? null,
  };
}

const config = resolveConfig();
if (!config) {
  const message = 'HiveCast demo requires MATRIX_API_KEY, MATRIX_CLOUD, and MATRIX_SPACE';
  if (checkOnly) {
    console.log(JSON.stringify({ ok: true, demo: 'hivecast-login', credentialsRequired: true, message }, null, 2));
    process.exit(0);
  }
  throw new Error(message);
}
if (checkOnly) {
  console.log(JSON.stringify({ ok: true, demo: 'hivecast-login', credentialsAvailable: true }, null, 2));
  process.exit(0);
}

const demoHome = process.env.MATRIX_DEMO_HOME
  ? resolve(process.env.MATRIX_DEMO_HOME)
  : mkdtempSync(join(tmpdir(), 'matrix-sdk-hivecast-login.'));
const keep = process.env.MATRIX_DEMO_KEEP === '1' || Boolean(process.env.MATRIX_DEMO_HOME);

try {
  const validation = await validateHiveCastKey(config);
  run(process.execPath, [
    matrixCli, 'configure',
    '--dir', demoHome,
    '--key', config.key,
    '--cloud', config.cloud,
    '--space', config.space,
  ]);

  const credentialPath = join(demoHome, '.matrix', 'credentials', 'matrix-api-key.json');
  const configPath = join(demoHome, '.matrix', 'config.json');
  if (!existsSync(credentialPath)) throw new Error(`Credential file was not written: ${credentialPath}`);
  if (!existsSync(configPath)) throw new Error(`Config file was not written: ${configPath}`);
  const writtenCredential = JSON.parse(readFileSync(credentialPath, 'utf8'));
  if (writtenCredential.key !== config.key) throw new Error('Written credential key does not match input key');
  if (writtenCredential.cloud !== config.cloud) throw new Error('Written credential cloud does not match input cloud');
  if (writtenCredential.space !== config.space) throw new Error('Written credential space does not match input space');

  console.log(JSON.stringify({
    ok: true,
    demo: 'hivecast-login',
    cloud: config.cloud,
    space: config.space,
    keyValidated: true,
    keyId: validation.keyId,
    fingerprint: validation.fingerprint,
    demoHome: keep ? demoHome : '(temporary, removed)',
    credentialPath: keep ? credentialPath : '(temporary, removed)',
  }, null, 2));
} finally {
  if (!keep) rmSync(demoHome, { recursive: true, force: true });
}
