import pool from '../../db';
import { CompliancePolicy, ComplianceRule, RAINMAKER_PROPERTY_ID } from './types';

let cachedPolicy: CompliancePolicy | null = null;
let cacheExpiry = 0;
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

function rowToPolicy(row: any): CompliancePolicy {
  return {
    id: row.id,
    version: row.version,
    name: row.name,
    isActive: row.is_active,
    propertyId: row.property_id || RAINMAKER_PROPERTY_ID,
    effectiveDate: row.effective_date ? row.effective_date.toISOString?.().split('T')[0] || String(row.effective_date) : null,
    prohibitedTerms: row.prohibited_terms || [],
    discouragedTerms: row.discouraged_terms || [],
    severityThresholds: row.severity_thresholds || { blockThreshold: 10, warnThreshold: 4 },
    rewriteVoicePrompt: row.rewrite_voice_prompt,
  };
}

export async function getActivePolicy(propertyId?: string): Promise<CompliancePolicy | null> {
  const pid = propertyId || RAINMAKER_PROPERTY_ID;

  // Only serve policies for rainmaker_web
  if (pid !== RAINMAKER_PROPERTY_ID) return null;

  if (cachedPolicy && Date.now() < cacheExpiry && cachedPolicy.propertyId === pid) {
    return cachedPolicy;
  }

  const { rows } = await pool.query(
    'SELECT * FROM rm_compliance_policies WHERE is_active = TRUE AND property_id = $1 LIMIT 1',
    [pid]
  );

  if (rows.length === 0) return null;

  cachedPolicy = rowToPolicy(rows[0]);
  cacheExpiry = Date.now() + CACHE_TTL;
  return cachedPolicy;
}

export function invalidatePolicyCache() {
  cachedPolicy = null;
  cacheExpiry = 0;
}

export async function createPolicyVersion(data: {
  prohibitedTerms: ComplianceRule[];
  discouragedTerms: ComplianceRule[];
  severityThresholds: { blockThreshold: number; warnThreshold: number };
  rewriteVoicePrompt?: string;
  name?: string;
  propertyId?: string;
}): Promise<CompliancePolicy> {
  const pid = data.propertyId || RAINMAKER_PROPERTY_ID;

  // Get next version number
  const { rows: maxRows } = await pool.query(
    'SELECT COALESCE(MAX(version), 0) + 1 AS next_version FROM rm_compliance_policies'
  );
  const nextVersion = maxRows[0].next_version;

  const { rows } = await pool.query(
    `INSERT INTO rm_compliance_policies
       (version, name, property_id, effective_date, prohibited_terms, discouraged_terms, severity_thresholds, rewrite_voice_prompt)
     VALUES ($1, $2, $3, CURRENT_DATE, $4, $5, $6, $7)
     RETURNING *`,
    [
      nextVersion,
      data.name || 'rainmaker_copy_safety',
      pid,
      JSON.stringify(data.prohibitedTerms),
      JSON.stringify(data.discouragedTerms),
      JSON.stringify(data.severityThresholds),
      data.rewriteVoicePrompt || null,
    ]
  );

  invalidatePolicyCache();
  return rowToPolicy(rows[0]);
}

export async function activatePolicy(version: number): Promise<void> {
  await pool.query('UPDATE rm_compliance_policies SET is_active = FALSE WHERE is_active = TRUE');
  await pool.query(
    'UPDATE rm_compliance_policies SET is_active = TRUE, updated_at = NOW() WHERE version = $1',
    [version]
  );
  invalidatePolicyCache();
}

export async function listPolicies(): Promise<CompliancePolicy[]> {
  const { rows } = await pool.query(
    'SELECT * FROM rm_compliance_policies ORDER BY version DESC'
  );
  return rows.map(rowToPolicy);
}

export async function seedV2Policy(): Promise<CompliancePolicy> {
  // Check if v2 already exists
  const { rows: existing } = await pool.query(
    'SELECT id FROM rm_compliance_policies WHERE version = 2'
  );
  if (existing.length > 0) {
    const { rows } = await pool.query('SELECT * FROM rm_compliance_policies WHERE version = 2');
    return rowToPolicy(rows[0]);
  }

  // ── PROHIBITED (BLOCK severity 10) ──
  const prohibitedTerms: ComplianceRule[] = [
    // Certainty / Guarantee
    { id: 'p1', pattern: '\\block\\b', label: 'Lock', severity: 10, category: 'certainty' },
    { id: 'p2', pattern: '\\b(mortal\\s+)?lock\\b', label: 'Mortal Lock', severity: 10, category: 'certainty' },
    { id: 'p3', pattern: '\\bguarantee[d]?\\b', label: 'Guarantee', severity: 10, category: 'certainty' },
    { id: 'p4', pattern: "\\bcan['\u2019]?t\\s+lose\\b", label: "Can't Lose", severity: 10, category: 'certainty' },
    { id: 'p5', pattern: '\\bsure\\s+thing\\b', label: 'Sure Thing', severity: 10, category: 'certainty' },
    { id: 'p6', pattern: "\\bcan['\u2019]?t\\s+miss\\b", label: "Can't Miss", severity: 10, category: 'certainty' },
    // Risk-Free / Free-Money
    { id: 'p7', pattern: '\\brisk[- ]?free\\b', label: 'Risk-Free', severity: 10, category: 'risk_free' },
    { id: 'p8', pattern: '\\bno[- ]?risk\\b', label: 'No-Risk', severity: 10, category: 'risk_free' },
    { id: 'p9', pattern: '\\bfree\\s+money\\b', label: 'Free Money', severity: 10, category: 'risk_free' },
    { id: 'p10', pattern: '\\beasy\\s+money\\b', label: 'Easy Money', severity: 10, category: 'risk_free' },
    { id: 'p11', pattern: "\\bcan['\u2019]?t\\s+go\\s+wrong\\b", label: "Can't Go Wrong", severity: 10, category: 'risk_free' },
    // CTA to Bet / Pressure
    { id: 'p12', pattern: '\\bhammer\\b', label: 'Hammer', severity: 10, category: 'cta' },
    { id: 'p13', pattern: '\\bsmash\\b', label: 'Smash', severity: 10, category: 'cta' },
    { id: 'p14', pattern: '\\bmax\\s+bet\\b', label: 'Max Bet', severity: 10, category: 'cta' },
    { id: 'p15', pattern: '\\bbet\\s+(this|now|it)\\b', label: 'Bet Now/This/It', severity: 10, category: 'cta' },
    { id: 'p16', pattern: '\\bplace\\s+your\\s+bet\\b', label: 'Place Your Bet', severity: 10, category: 'cta' },
    { id: 'p17', pattern: '\\bwager\\b', label: 'Wager', severity: 10, category: 'cta' },
    { id: 'p18', pattern: '\\bcash\\s+(this|it)\\b', label: 'Cash This/It', severity: 10, category: 'cta' },
    { id: 'p19', pattern: '\\bparlay\\b', label: 'Parlay', severity: 10, category: 'cta' },
    // Chasing Losses
    { id: 'p20', pattern: '\\bchase\\s+loss(es)?\\b', label: 'Chase Losses', severity: 10, category: 'chase' },
    { id: 'p21', pattern: '\\bdouble\\s+down\\b', label: 'Double Down', severity: 10, category: 'chase' },
    { id: 'p22', pattern: '\\bget\\s+it\\s+back\\b', label: 'Get It Back', severity: 10, category: 'chase' },
    { id: 'p23', pattern: '\\brecover\\s+losses\\b', label: 'Recover Losses', severity: 10, category: 'chase' },
    { id: 'p24', pattern: '\\bmake\\s+it\\s+back\\b', label: 'Make It Back', severity: 10, category: 'chase' },
  ];

  // ── DISCOURAGED (WARN, rewrite preferred) ──
  const discouragedTerms: ComplianceRule[] = [
    { id: 'd1', pattern: '\\bbest\\s+bet\\b', label: 'Best Bet', severity: 6, category: 'soft' },
    { id: 'd2', pattern: '\\btop\\s+play\\b', label: 'Top Play', severity: 5, category: 'soft' },
    { id: 'd3', pattern: '\\block\\s+it\\s+in\\b', label: 'Lock It In', severity: 7, category: 'soft' },
    { id: 'd4', pattern: '\\bwinner\\b', label: 'Winner', severity: 3, category: 'soft' },
    { id: 'd5', pattern: '\\bprint\\s+money\\b', label: 'Print Money', severity: 5, category: 'soft' },
    { id: 'd6', pattern: '\\btake\\s+the\\s+\\w+\\b', label: 'Take The...', severity: 5, category: 'soft' },
    { id: 'd7', pattern: '\\bfade\\s+\\w+\\b', label: 'Fade...', severity: 5, category: 'soft' },
  ];

  const voicePrompt = `You are the Rainmaker editorial voice — witty, playful, and slightly unhinged (in a fun way). You see sports through a weather lens.

PERSONALITY:
- Use weather/storm metaphors freely: radar, pressure systems, tailwinds, turbulence, barometric readings, storm fronts, forecast conditions
- Be clever and entertaining — make readers smirk, not cringe
- Sound like a charismatic meteorologist who wandered into a sports newsroom
- Use uncertainty language naturally: "may", "could", "worth watching", "one angle to consider", "keep an eye on", "the conditions suggest"

ABSOLUTE RULES:
1. REMOVE all gambling-promotional language — every single instance
2. REMOVE all certainty framing ("guaranteed", "lock", "can't lose", "sure thing")
3. REMOVE all calls-to-action to bet ("hammer", "smash", "max bet", "bet this", "place your bet", "wager", "cash this", "parlay")
4. REMOVE all risk-free framing ("risk-free", "free money", "easy money", "can't go wrong")
5. REMOVE all chasing language ("chase losses", "double down", "get it back", "recover losses", "make it back")
6. NEVER be crude, profane, hateful, sexual, or insulting
7. NEVER tell users what to do — preserve free will
8. NEVER guarantee outcomes
9. Replace removed terms with weather-themed editorial alternatives that maintain the analytical insight
10. Keep the same factual content and approximate length

EXAMPLE REWRITES:
- "This is a lock" → "The radar's picking up some interesting signals here—worth watching, not a promise."
- "Guaranteed winner" → "Nothing's guaranteed, but the conditions make this matchup genuinely interesting."
- "Hammer the over" → "Keep an eye on the over—there's some weather building around this angle."
- "Risk-free play" → "No freebies in the wild—just context, signals, and a little chaos."
- "Best bet of the day" → "The most intriguing forecast of the day, if you ask the barometer."`;

  // Deactivate v1
  await pool.query('UPDATE rm_compliance_policies SET is_active = FALSE WHERE is_active = TRUE');

  const { rows } = await pool.query(
    `INSERT INTO rm_compliance_policies
       (version, name, is_active, property_id, effective_date, prohibited_terms, discouraged_terms, severity_thresholds, rewrite_voice_prompt)
     VALUES ($1, $2, TRUE, $3, CURRENT_DATE, $4, $5, $6, $7)
     RETURNING *`,
    [
      2,
      'rainmaker_copy_safety',
      RAINMAKER_PROPERTY_ID,
      JSON.stringify(prohibitedTerms),
      JSON.stringify(discouragedTerms),
      JSON.stringify({ blockThreshold: 10, warnThreshold: 3 }),
      voicePrompt,
    ]
  );

  invalidatePolicyCache();
  return rowToPolicy(rows[0]);
}

// Keep backward compat — alias
export const seedDefaultPolicy = seedV2Policy;
