import 'dotenv/config';
import fs from 'fs';
import path from 'path';
import pool from '../db';

const HOME = process.env.HOME || '/home/administrator';
const ALERTS_DIR = path.join(HOME, '.openclaw', 'cron');
const ALERTS_PATH = path.join(ALERTS_DIR, 'cap-alerts.json');
const STATE_PATH = path.join(ALERTS_DIR, 'cap-monitor-state.json');
const LOG_PATH = '/var/log/rainmaker/cap-monitor.log';

const WEATHER_REPORT_DAILY_CAP = Number(process.env.WEATHER_REPORT_DAILY_CAP || 600);
const WARN_THRESHOLD = Number(process.env.CAP_WARN_THRESHOLD || 0.9);

function nowET() {
  return new Date().toLocaleString('en-CA', { timeZone: 'America/New_York' }).replace(',', '');
}

function todayET() {
  return new Date().toLocaleDateString('en-CA', { timeZone: 'America/New_York' });
}

function readJson(file: string, fallback: any) {
  try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return fallback; }
}

function writeJson(file: string, data: any) {
  fs.mkdirSync(path.dirname(file), { recursive: true });
  fs.writeFileSync(file, JSON.stringify(data, null, 2));
}

function appendLog(message: string) {
  fs.mkdirSync(path.dirname(LOG_PATH), { recursive: true });
  fs.appendFileSync(LOG_PATH, `[${new Date().toISOString()}] ${message}\n`);
}

async function checkWeatherReportCap() {
  const dateET = todayET();
  const { rows } = await pool.query(
    `SELECT COUNT(*)::int AS cnt FROM rm_forecast_precomputed WHERE date_et = $1`,
    [dateET]
  );
  const used = rows[0]?.cnt || 0;
  const cap = WEATHER_REPORT_DAILY_CAP;
  const pct = cap > 0 ? used / cap : 0;
  const threshold = Math.ceil(cap * WARN_THRESHOLD);
  const status = used >= cap ? 'exceeded' : (used >= threshold ? 'warning' : 'ok');

  return {
    id: 'weather-report-daily-cap',
    name: 'Weather Report Daily Cap',
    scope: 'daily',
    dateET,
    used,
    cap,
    remaining: Math.max(0, cap - used),
    percent: Number((pct * 100).toFixed(1)),
    warnAt: threshold,
    status,
    details: `rm_forecast_precomputed rows for ${dateET}: ${used}/${cap} (${(pct * 100).toFixed(1)}%)`,
    owner: 'Rainmaker',
    sourceJob: 'weather-report',
    recommendedAction: used >= cap
      ? 'Cap reached. Raise WEATHER_REPORT_DAILY_CAP or run targeted league-only refreshes.'
      : used >= threshold
        ? 'Cap is close. Review slate size and decide whether to raise or deny based on obligations.'
        : 'No action needed.',
    checkedAt: new Date().toISOString(),
  };
}

async function main() {
  const state = readJson(STATE_PATH, { alertsSent: {} });
  const weather = await checkWeatherReportCap();
  const alerts = {
    updatedAt: new Date().toISOString(),
    timezone: 'America/New_York',
    thresholdPercent: WARN_THRESHOLD * 100,
    alerts: [weather],
  };
  writeJson(ALERTS_PATH, alerts);

  const key = `${weather.id}:${weather.dateET}:${weather.status}`;
  if (weather.status === 'warning' || weather.status === 'exceeded') {
    if (!state.alertsSent[key]) {
      appendLog(`ALERT ${weather.status.toUpperCase()} — ${weather.name} — ${weather.details} — ${weather.recommendedAction}`);
      state.alertsSent[key] = { sentAt: new Date().toISOString(), snapshot: weather };
    } else {
      appendLog(`CHECK ${weather.status.toUpperCase()} — ${weather.name} — ${weather.details}`);
    }
  } else {
    appendLog(`CHECK OK — ${weather.name} — ${weather.details}`);
  }

  // prune prior-day sent markers
  const today = weather.dateET;
  for (const k of Object.keys(state.alertsSent || {})) {
    if (!k.includes(`:${today}:`)) delete state.alertsSent[k];
  }
  writeJson(STATE_PATH, state);
  await pool.end();
}

main().catch(async (err) => {
  appendLog(`ERROR — ${err?.stack || err?.message || String(err)}`);
  try { await pool.end(); } catch {}
  process.exit(1);
});
