import fs from 'node:fs';
import path from 'node:path';
import { spawnSync } from 'node:child_process';
import { fileURLToPath } from 'node:url';
import { loadEnv } from './env.js';

loadEnv();

const moduleDir = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(moduleDir, '../../..');

function argValue(name: string) {
  const prefix = `${name}=`;
  return process.argv.slice(2).find(arg => arg.startsWith(prefix))?.slice(prefix.length);
}

function hasArg(name: string) {
  return process.argv.slice(2).includes(name);
}

function resolvePath(input: string, fallbackBase = process.cwd()) {
  return path.resolve(fallbackBase, input);
}

function findPython() {
  const candidates = [
    process.env.PYTHON,
    process.env.PYTHON_BIN,
    'python',
    'py',
    'python3',
  ].filter(Boolean) as string[];

  for (const candidate of candidates) {
    const result = spawnSync(candidate, ['--version'], { encoding: 'utf8' });
    if (result.status === 0) return candidate;
  }
  throw new Error('Python 3 is required for SQLite export. Set PYTHON or install Python 3.');
}

const sqliteDir = resolvePath(
  argValue('--sqlite-dir') || process.env.PB_SQLITE_DIR || path.join(repoRoot, '参考', '旧题库数据库文件'),
);
const dataDb = resolvePath(argValue('--data-db') || process.env.PB_SQLITE_DATA_DB || path.join(sqliteDir, 'data.db'));
const auxDb = resolvePath(argValue('--aux-db') || process.env.PB_SQLITE_AUX_DB || path.join(sqliteDir, 'auxiliary.db'));
const storageDir = resolvePath(
  argValue('--storage-dir') || process.env.PB_SQLITE_STORAGE_DIR || path.join(sqliteDir, 'storage'),
);
const exportDir = resolvePath(argValue('--export-dir') || process.env.PB_EXPORT_DIR || path.join(repoRoot, 'pb_export'));
const collections = argValue('--collections') || process.env.PB_SQLITE_COLLECTIONS || '';
const batchSize = argValue('--batch-size') || process.env.PB_SQLITE_BATCH_SIZE || '1000';
const includeSystem = hasArg('--include-system') || process.env.PB_SQLITE_INCLUDE_SYSTEM === 'true';
const includeSensitiveIdentities =
  hasArg('--include-sensitive-identities') || process.env.PB_SQLITE_INCLUDE_SENSITIVE_IDENTITIES === 'true';
const includeAuxLogs = hasArg('--include-aux-logs') || process.env.PB_SQLITE_INCLUDE_AUX_LOGS === 'true';

if (!fs.existsSync(dataDb)) {
  throw new Error(`PocketBase SQLite data.db not found: ${dataDb}`);
}

if (!includeSensitiveIdentities) {
  console.warn('[pb:export:sqlite] openid/unionid/session-like fields are redacted in JSON export by default.');
}
console.warn(`[pb:export:sqlite] reading SQLite source in read-only mode: ${dataDb}`);
console.warn(`[pb:export:sqlite] writing collection JSON to: ${exportDir}`);

const python = findPython();
const script = path.join(moduleDir, 'sqlite-exporter.py');
const args = [
  script,
  '--data-db',
  dataDb,
  '--export-dir',
  exportDir,
  '--batch-size',
  batchSize,
];

if (fs.existsSync(auxDb)) args.push('--aux-db', auxDb);
if (fs.existsSync(storageDir)) args.push('--storage-dir', storageDir);
if (collections) args.push('--collections', collections);
if (includeSystem) args.push('--include-system');
if (includeSensitiveIdentities) args.push('--include-sensitive-identities');
if (includeAuxLogs) args.push('--include-aux-logs');

const result = spawnSync(python, args, {
  cwd: repoRoot,
  encoding: 'utf8',
  stdio: ['ignore', 'pipe', 'pipe'],
});

if (result.stderr) process.stderr.write(result.stderr);
if (result.stdout) {
  try {
    const payload = JSON.parse(result.stdout);
    console.log(
      [
        '[pb:export:sqlite] export completed',
        `collections=${payload.collectionCount}`,
        `records=${payload.recordCount}`,
        `manifest=${path.join(exportDir, 'sqlite-export-manifest.json')}`,
        payload.storage ? `storageFiles=${payload.storage.fileCount}` : 'storageFiles=0',
      ].join(' '),
    );
  } catch {
    process.stdout.write(result.stdout);
  }
}

if (result.error) throw result.error;
if (result.status !== 0) {
  process.exit(result.status || 1);
}
