'use strict';

const fs = require('fs');
const path = require('path');
const http = require('http');
const Core = require('./core.js');

const PORT = Number(process.env.PORT || 4173);
const HOST = '127.0.0.1';
const STATE_FILE = process.env.MARKETING_BOSS_STATE_FILE || path.join(__dirname, 'marketing-boss-state.json');
const OUTPUT_DIR = process.env.MARKETING_BOSS_OUTPUT_DIR || path.join(__dirname, 'marketing-output');
const FIXTURE = process.env.MARKETING_BOSS_SYNC_FIXTURE || '';

function readJson(file, fallback) {
  try { return JSON.parse(fs.readFileSync(file, 'utf8')); } catch (_) { return fallback; }
}
function writeJsonAtomic(file, value) {
  fs.mkdirSync(path.dirname(file), { recursive: true });
  const temp = `${file}.tmp`;
  fs.writeFileSync(temp, JSON.stringify(value, null, 2), { encoding: 'utf8', mode: 0o600 });
  fs.renameSync(temp, file);
}
function requestJson(method, pathname, body) {
  return new Promise((resolve, reject) => {
    const encoded = body == null ? null : Buffer.from(JSON.stringify(body));
    const req = http.request({ hostname: HOST, port: PORT, path: pathname, method, timeout: 30000, headers: encoded ? { 'Content-Type': 'application/json', 'Content-Length': encoded.length } : {} }, (res) => {
      const chunks = [];
      res.on('data', (chunk) => chunks.push(chunk));
      res.on('end', () => {
        let payload = {};
        try { payload = JSON.parse(Buffer.concat(chunks).toString('utf8') || '{}'); } catch (_) {}
        if (res.statusCode < 200 || res.statusCode >= 300) return reject(new Error(payload.error || `HTTP ${res.statusCode}`));
        resolve(payload);
      });
    });
    req.on('timeout', () => req.destroy(new Error('Marketing Boss service timed out.')));
    req.on('error', reject);
    if (encoded) req.write(encoded);
    req.end();
  });
}
function perthDate(offsetDays = 0) {
  const now = new Date(Date.now() + 8 * 60 * 60 * 1000 + offsetDays * 24 * 60 * 60 * 1000);
  return now.toISOString().slice(0, 10);
}
function addDays(isoDate, days) {
  const date = new Date(`${isoDate}T00:00:00Z`);
  date.setUTCDate(date.getUTCDate() + days);
  return date.toISOString().slice(0, 10);
}
function escapeHtml(value) {
  return String(value == null ? '' : value).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#039;');
}
function renderReview(state, campaign, report) {
  const posts = campaign ? state.posts.filter((post) => post.campaignId === campaign.id && post.approvalStatus !== 'rejected') : [];
  const cards = posts.map((post) => `<article><div class="meta"><strong>${escapeHtml(post.productName)}</strong><span>${escapeHtml(Core.platformLabel(post.platform))} · ${escapeHtml(post.scheduledDate)} ${escapeHtml(post.scheduledTime)}</span></div><pre>${escapeHtml(post.caption)}\n\n${escapeHtml(post.hashtags)}\n${escapeHtml(post.callToAction)}</pre></article>`).join('');
  return `<!doctype html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Marketing Boss Review</title><style>body{font-family:system-ui;background:#09090b;color:#fafafa;margin:0}header{padding:28px;background:#18181b;position:sticky;top:0}main{max-width:1050px;margin:auto;padding:24px}.banner{background:#32155b;border:1px solid #7c3aed;border-radius:16px;padding:18px;margin-bottom:20px}article{background:#18181b;border:1px solid #3f3f46;border-radius:16px;padding:18px;margin:14px 0}.meta{display:flex;justify-content:space-between;gap:20px}.meta span{color:#a1a1aa}pre{white-space:pre-wrap;font-family:inherit;line-height:1.55;color:#e4e4e7}code{color:#86efac}</style></head><body><header><h1>Marketing Boss · Ray Review</h1><p>Drafts only. Nothing is approved or published.</p></header><main><div class="banner"><strong>Status: ${escapeHtml(report.status)}</strong><p>${escapeHtml(report.message)}</p><code>${escapeHtml(STATE_FILE)}</code></div>${cards || '<article>No campaign drafts are available yet.</article>'}</main></body></html>`;
}

async function main() {
  fs.mkdirSync(OUTPUT_DIR, { recursive: true });
  let state = Core.ensureState(readJson(STATE_FILE, Core.resetToEmpty()));
  const report = { agent: 'marketing-boss', boundary: 'SHIRE3D_ONLY', startedAt: new Date().toISOString(), status: 'STARTING', message: '', sync: null, campaignId: null, productCount: 0, postCount: 0, approvalState: 'RAY_REVIEW_REQUIRED' };
  try {
    const syncPayload = FIXTURE ? readJson(FIXTURE, null) : await requestJson('POST', '/api/sync-products', { sourceIds: ['shire3d_com', 'shire3d_com_au', 'shire3d_etsy'], force: false });
    if (!syncPayload) throw new Error('The configured sync fixture could not be read.');
    const synced = Core.applyCatalogSync(state, syncPayload);
    state = synced.state;
    report.sync = { added: synced.added, updated: synced.updated, unchanged: synced.unchanged, failed: synced.failed };

    const today = perthDate(0);
    const month = today.slice(0, 7);
    let campaign = state.campaigns.find((item) => item.month === month && ['ray_review', 'needs_reapproval', 'approved'].includes(item.status));
    if (!campaign) {
      const generated = Core.generateCampaign(state, {
        productMode: 'all', month,
        platforms: ['facebook', 'instagram', 'linkedin', 'tiktok', 'youtube_shorts'],
        frequency: '5 posts per week',
        goal: 'Bring more qualified customers to SHIRE3D quickly using every live, marketable product.',
        tone: 'Bold, warm, customer-friendly, useful and honest.'
      });
      state = generated.state;
      campaign = generated.campaign;
      const active = state.posts.filter((post) => post.campaignId === campaign.id && post.approvalStatus !== 'rejected');
      active.forEach((post, index) => { post.scheduledDate = addDays(today, index + 1); post.updatedAt = new Date().toISOString(); });
      campaign.goal = 'Immediate customer-growth sprint across every live SHIRE3D product.';
      campaign.updatedAt = new Date().toISOString();
    }

    const posts = state.posts.filter((post) => post.campaignId === campaign.id && post.approvalStatus !== 'rejected');
    report.status = 'DRAFT_CAMPAIGN_READY';
    report.message = `${posts.length} customer-facing drafts across ${campaign.productCount} live products are ready for Ray's review. Nothing was approved or published.`;
    report.campaignId = campaign.id;
    report.productCount = campaign.productCount;
    report.postCount = posts.length;
    writeJsonAtomic(STATE_FILE, state);
    await requestJson('POST', '/api/agent-state', { state });
    fs.writeFileSync(path.join(OUTPUT_DIR, 'latest-campaign-review.html'), renderReview(state, campaign, report), 'utf8');
  } catch (error) {
    report.status = 'BLOCKED';
    report.message = error.message;
    writeJsonAtomic(STATE_FILE, state);
    fs.writeFileSync(path.join(OUTPUT_DIR, 'latest-campaign-review.html'), renderReview(state, null, report), 'utf8');
  }
  report.completedAt = new Date().toISOString();
  writeJsonAtomic(path.join(OUTPUT_DIR, 'latest-run.json'), report);
  console.log(JSON.stringify(report, null, 2));
  if (report.status === 'BLOCKED') process.exitCode = 2;
}

main().catch((error) => { console.error(error); process.exitCode = 1; });
