// Report metadata store + report schedules — small JSON files under data/.
//   • reports-index.json: what each generated file IS (client, style, format,
//     how it was produced) so the Reports page can group, search and label.
//   • report-schedules.json: per-client recurring report definitions run by
//     the in-process scheduler (weekly/monthly/daily, PDF or PowerPoint,
//     optionally emailed).

import fs from 'node:fs';
import path from 'node:path';
import crypto from 'node:crypto';
import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const DATA_DIR = path.join(__dirname, '..', 'data');
const IDX_FILE = path.join(DATA_DIR, 'reports-index.json');
const SCH_FILE = path.join(DATA_DIR, 'report-schedules.json');

function loadJson(file, fallback) {
  try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch { return fallback; }
}
function saveJson(file, obj) {
  fs.mkdirSync(DATA_DIR, { recursive: true });
  fs.writeFileSync(file, JSON.stringify(obj, null, 2));
}

// ── report index ────────────────────────────────────────────────────────
export function recordReport({ file, siteId, title, style, format, source }) {
  if (!file) return;
  const idx = loadJson(IDX_FILE, {});
  idx[file] = {
    siteId: siteId || null,
    title: String(title || '').slice(0, 160),
    style: style || null,
    format: format || (file.endsWith('.pptx') ? 'pptx' : file.endsWith('.pdf') ? 'pdf' : 'html'),
    source: source || 'manual', // manual | ai | schedule
    at: Date.now(),
  };
  // Prune entries whose files are gone, and cap the index.
  const names = Object.keys(idx);
  if (names.length > 1200) {
    const sorted = names.sort((a, b) => (idx[a].at || 0) - (idx[b].at || 0));
    for (const n of sorted.slice(0, names.length - 1000)) delete idx[n];
  }
  saveJson(IDX_FILE, idx);
}

export function reportIndex() {
  return loadJson(IDX_FILE, {});
}

export function forgetReport(file) {
  const idx = loadJson(IDX_FILE, {});
  if (idx[file]) { delete idx[file]; saveJson(IDX_FILE, idx); }
}

// ── schedules ───────────────────────────────────────────────────────────
// { id, siteId, style: full|table|monitoring, format: pdf|pptx,
//   frequency: daily|weekly|monthly, day, hour, range, market, emails,
//   enabled, lastRun, lastFile, createdBy }
export function listSchedules() {
  return loadJson(SCH_FILE, []);
}

export function saveSchedule(s) {
  const all = loadJson(SCH_FILE, []);
  const clean = {
    id: s.id || crypto.randomBytes(6).toString('hex'),
    siteId: String(s.siteId || 'all'),
    style: ['full', 'table', 'monitoring'].includes(s.style) ? s.style : 'full',
    format: s.format === 'pptx' ? 'pptx' : 'pdf',
    frequency: ['daily', 'weekly', 'monthly'].includes(s.frequency) ? s.frequency : 'weekly',
    day: Math.max(0, Math.min(28, Number(s.day) || (s.frequency === 'monthly' ? 1 : 1))),
    hour: Math.max(0, Math.min(23, Number(s.hour ?? 7))),
    range: ['7d', '28d', '90d', 'mtd', '12mo'].includes(s.range) ? s.range : '28d',
    market: s.market ? String(s.market).slice(0, 80) : null,
    emails: String(s.emails || '').split(',').map((x) => x.trim()).filter((x) => /.+@.+\..+/.test(x)).slice(0, 10).join(','),
    enabled: s.enabled !== false,
    lastRun: s.lastRun || null,
    lastFile: s.lastFile || null,
    createdBy: String(s.createdBy || '').slice(0, 80),
  };
  const i = all.findIndex((x) => x.id === clean.id);
  if (i >= 0) all[i] = { ...all[i], ...clean };
  else all.push(clean);
  saveJson(SCH_FILE, all);
  return clean;
}

export function deleteSchedule(id) {
  const all = loadJson(SCH_FILE, []);
  const next = all.filter((x) => x.id !== id);
  saveJson(SCH_FILE, next);
  return next.length < all.length;
}

export function markScheduleRun(id, file) {
  const all = loadJson(SCH_FILE, []);
  const s = all.find((x) => x.id === id);
  if (s) {
    s.lastRun = new Date().toISOString().slice(0, 10);
    s.lastFile = file || s.lastFile || null;
    saveJson(SCH_FILE, all);
  }
}
