import fs from 'node:fs';
import path from 'node:path';

const DATA_DIR = process.env.DATA_DIR ?? '/data';
// Save state inside /data/sounds/ — this directory is volume-mounted and
// survives container recreation. The old /data/hub-state.json was lost on
// every redeploy because only /data/sounds/ is persistently mounted.
const SOUNDS_DIR = path.join(DATA_DIR, 'sounds');
const stateFile = path.join(SOUNDS_DIR, 'hub-state.json');
const backupFile = stateFile + '.bak';
const tmpFile = stateFile + '.tmp';

// Legacy location (will be migrated automatically)
const legacyStateFile = path.join(DATA_DIR, 'hub-state.json');

let state: Record<string, any> = {};
let lastSaveOk = false;

export function loadState(): void {
  console.log(`[State] DATA_DIR=${DATA_DIR}, stateFile=${stateFile}`);

  // Check if sounds dir exists and is writable
  try {
    fs.mkdirSync(SOUNDS_DIR, { recursive: true });
    const testFile = path.join(SOUNDS_DIR, '.write-test');
    fs.writeFileSync(testFile, 'ok');
    fs.unlinkSync(testFile);
    console.log(`[State] sounds dir is writable`);
  } catch (e) {
    console.error(`[State] ⚠ sounds dir is NOT writable:`, e);
  }

  // List existing state files for diagnostics
  try {
    const files = fs.readdirSync(SOUNDS_DIR).filter(f => f.includes('state') || f.includes('hub'));
    console.log(`[State] State files in sounds/: ${files.join(', ') || '(none)'}`);
  } catch {}

  // Try new location, then backup, then legacy location
  const candidates = [stateFile, backupFile, legacyStateFile];
  for (const file of candidates) {
    try {
      if (fs.existsSync(file)) {
        const raw = fs.readFileSync(file, 'utf-8');
        state = JSON.parse(raw);
        const keys = Object.keys(state);
        const favCount = Array.isArray(state.radio_favorites) ? state.radio_favorites.length : 0;
        console.log(`[State] ✓ Loaded from ${file} (${keys.length} keys: ${keys.join(', ')})`);
        console.log(`[State]   radio_favorites: ${favCount} entries`);
        // If loaded from legacy location, migrate to new location
        if (file === legacyStateFile) {
          console.log(`[State] Migrating from legacy ${legacyStateFile} → ${stateFile}`);
          saveState();
          try { fs.unlinkSync(legacyStateFile); } catch {}
        }
        // Create backup on successful load
        try { fs.copyFileSync(stateFile, backupFile); } catch {}
        lastSaveOk = true;
        return;
      }
    } catch (e) {
      console.error(`[State] Failed to load ${file}:`, e);
    }
  }
  console.log('[State] No existing state found, starting fresh');
}

export function saveState(): void {
  try {
    fs.mkdirSync(path.dirname(stateFile), { recursive: true });
    const json = JSON.stringify(state, null, 2);
    // Atomic write: write to tmp file, then rename
    fs.writeFileSync(tmpFile, json);
    fs.renameSync(tmpFile, stateFile);
    lastSaveOk = true;
  } catch (e) {
    console.error('[State] ✗ Failed to save:', e);
    lastSaveOk = false;
    // Fallback: try direct write if rename failed
    try {
      fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
      console.log('[State] Fallback direct write succeeded');
      lastSaveOk = true;
    } catch (e2) {
      console.error('[State] ✗ Fallback write also failed:', e2);
    }
  }
}

export function getState<T = any>(key: string, defaultValue?: T): T {
  return (state[key] as T) ?? (defaultValue as T);
}

export function setState(key: string, value: any): void {
  state[key] = value;
  saveState();
}

export function getFullState(): Record<string, any> {
  return { ...state };
}

/** Diagnostic info for health endpoint */
export function getStateDiag(): Record<string, any> {
  let fileExists = false;
  let fileSize = 0;
  let fileFavCount = 0;
  try {
    if (fs.existsSync(stateFile)) {
      fileExists = true;
      const stat = fs.statSync(stateFile);
      fileSize = stat.size;
      const parsed = JSON.parse(fs.readFileSync(stateFile, 'utf-8'));
      fileFavCount = Array.isArray(parsed.radio_favorites) ? parsed.radio_favorites.length : 0;
    }
  } catch {}
  const memFavCount = Array.isArray(state.radio_favorites) ? state.radio_favorites.length : 0;
  return {
    stateFile,
    fileExists,
    fileSize,
    fileFavCount,
    memoryFavCount: memFavCount,
    lastSaveOk,
  };
}
