← back to Designer Wallcoverings

DW-Agents/dw-agents/agent-legal-team/legal-agent.ts

2769 lines

/**
 * DW Legal Team - Settlement Compliance Monitor
 *
 * PRIORITY #1: SETTLEMENT AGREEMENT COMPLIANCE
 *
 * This agent continuously monitors the product catalog for settlement violations
 * and provides legal guidance on tropical design patterns.
 *
 * SETTLEMENT CRITERIA (MUST BE ENFORCED):
 *
 * A product is PROHIBITED if it contains BOTH Part A AND Part B:
 *
 * Part A - Prohibited Design (ALL three must be present):
 *   1. Repeating patterns with directional variation amongst leaves/palm fronds
 *   2. Open space between leaves
 *   3. More than one ink color
 *
 * Part B - Prohibited Specific Elements (ANY of these):
 *   - Bananas (FRUIT) or banana pods (NOT leaves - banana leaves are OK)
 *   - Grapes (fruit/clusters)
 *   - Birds
 *   - Butterflies
 *
 * Acceptable Tropical Design (at least ONE must be present):
 *   1. Tree trunks
 *   2. Clearly represented branches
 *   3. Fruit or animal elements (EXCEPT prohibited ones)
 */

import 'dotenv/config';
import Anthropic from '@anthropic-ai/sdk';
import express from 'express';
import cookieParser from 'cookie-parser';
import session from 'express-session';
import svgCaptcha from 'svg-captcha';
import { chromium } from 'playwright';
import fetch from 'node-fetch';
import { GoogleGenerativeAI } from '@google/generative-ai';
import { exec } from 'child_process';
import { requireAuth as ssoAuth, handleLogin, setSSOToken, SSO_TOKEN_NAME, SSO_TOKEN_VALUE } from './shared-auth';
// import { AgentMemory } from './shared-memory-system';
// chatMiddleware disabled - uses import.meta.url (ESM-only) which crashes in CJS/tsx mode
// import { chatMiddleware } from '../shared-chat-integration';
const { getUniversalHeader } = require('../shared-ui-components.js');

const app = express();
const PORT = 9878;

// Global Authentication - MUST come before any other middleware
app.use(cookieParser());

// Initialize agent memory system
// const agentMemory = new AgentMemory('legal-team');
// console.log('📚 Memory system initialized for legal-team');

// Analysis cache - stores results to avoid re-analyzing
const analysisCache = new Map<string, { compliant: boolean; analysis: string; timestamp: number }>();

// PostgreSQL query helper using psql CLI (avoids pg module dependency)
function psqlQuery(sql: string): Promise<any[]> {
  return new Promise((resolve, reject) => {
    const escaped = sql.replace(/'/g, "'\\''");
    exec(`PGPASSWORD=${process.env.PGPASSWORD||''} psql -U dw_admin -h 127.0.0.1 -d dw_unified -t -A -F '|||' -c '${escaped}'`, { timeout: 15000 }, (err, stdout, stderr) => {
      if (err) { reject(new Error(stderr || err.message)); return; }
      const lines = stdout.trim().split('\n').filter(l => l.length > 0);
      resolve(lines);
    });
  });
}

function psqlQueryJSON(sql: string): Promise<any[]> {
  return new Promise((resolve, reject) => {
    const fullSql = `SELECT json_agg(t) FROM (${sql}) t`;
    const escaped = fullSql.replace(/'/g, "'\\''");
    exec(`PGPASSWORD=${process.env.PGPASSWORD||''} psql -U dw_admin -h 127.0.0.1 -d dw_unified -t -A -c '${escaped}'`, { timeout: 15000 }, (err, stdout, stderr) => {
      if (err) { reject(new Error(stderr || err.message)); return; }
      try {
        const result = JSON.parse(stdout.trim() || '[]');
        resolve(result || []);
      } catch { resolve([]); }
    });
  });
}

function psqlExec(sql: string): Promise<void> {
  return new Promise((resolve, reject) => {
    const escaped = sql.replace(/'/g, "'\\''");
    exec(`PGPASSWORD=${process.env.PGPASSWORD||''} psql -U dw_admin -h 127.0.0.1 -d dw_unified -c '${escaped}'`, { timeout: 15000 }, (err, stdout, stderr) => {
      if (err) { reject(new Error(stderr || err.message)); return; }
      resolve();
    });
  });
}

// Save violation to PostgreSQL
async function saveViolationToDB(violation: { productId: string; sku: string; title: string; url: string; analysis: string; vendor?: string; imageUrl?: string; riskLevel?: string }) {
  try {
    const title = (violation.title || '').replace(/'/g, "''");
    const analysis = (violation.analysis || '').replace(/'/g, "''");
    const vendor = (violation.vendor || '').replace(/'/g, "''");
    const imgUrl = (violation.imageUrl || '').replace(/'/g, "''");
    const srcUrl = (violation.url || '').replace(/'/g, "''");
    const sku = (violation.sku || '').replace(/'/g, "''");
    const pid = (violation.productId || '').replace(/'/g, "''");
    await psqlExec(`INSERT INTO legal_violations (product_id, shopify_product_id, sku, title, vendor, image_url, source_url, analysis, risk_level, status, detected_at) VALUES ('${pid}', '${pid}', '${sku}', '${title}', '${vendor}', '${imgUrl}', '${srcUrl}', '${analysis}', '${violation.riskLevel || 'HIGH'}', 'open', NOW()) ON CONFLICT DO NOTHING`);
  } catch (e: any) {
    console.error('Error saving violation to DB:', e.message);
  }
}

// Load violations from PostgreSQL (date-ordered)
async function loadViolationsFromDB(limit = 100, status = 'all'): Promise<any[]> {
  try {
    const whereClause = status === 'all' ? '' : `WHERE status = '${status}'`;
    return await psqlQueryJSON(`SELECT * FROM legal_violations ${whereClause} ORDER BY detected_at DESC LIMIT ${limit}`);
  } catch (e: any) {
    console.error('Error loading violations from DB:', e.message);
    return [];
  }
}

// Report violations to CFO dashboard
async function reportToCFO(violations: any[]) {
  try {
    const summary = violations.map((v: any) => `- ${v.title} (SKU: ${v.sku}, Risk: ${v.risk_level})`).join('\n');
    const message = {
      from: 'Legal Team',
      fromPort: 9878,
      subject: `Legal Alert: ${violations.length} Settlement Violation${violations.length > 1 ? 's' : ''} Detected`,
      body: `SETTLEMENT COMPLIANCE ALERT\n\nThe Legal Team has detected ${violations.length} potential settlement violation(s) requiring immediate attention:\n\n${summary}\n\nPlease review and take action on the Legal Team dashboard: http://45.61.58.125:9878`,
      priority: 'critical',
      timestamp: new Date().toISOString()
    };

    const resp = await fetch('http://localhost:7121/api/messages', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(message)
    });
    if (resp.ok) {
      console.log('CFO notified of violations');
      for (const v of violations) {
        await psqlExec(`UPDATE legal_violations SET reported_to_cfo = true, cfo_report_at = NOW() WHERE id = ${v.id}`);
      }
    }
    return resp.ok;
  } catch (e: any) {
    console.error('Error reporting to CFO:', e.message);
    return false;
  }
}

const SHOPIFY_STORE = process.env.SHOPIFY_STORE_DOMAIN || 'designer-laboratory-sandbox.myshopify.com';
const SHOPIFY_TOKEN = process.env.SHOPIFY_ADMIN_ACCESS_TOKEN || process.env.SHOPIFY_ADMIN_TOKEN;
const API_VERSION = process.env.SHOPIFY_ADMIN_API_VERSION || '2024-07';

const anthropic = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

// Settlement compliance statistics
let stats = {
  totalScanned: 0,
  violations: 0,
  compliant: 0,
  needsReview: 0,
  lastScan: null as Date | null,
  lastViolation: null as { title: string; id: string; timestamp: Date } | null,
  importsMonitored: 0,
  lastImport: null as { title: string; status: string; timestamp: Date } | null,
};

// Recent activity log for real-time monitoring
const activityLog: Array<{
  timestamp: Date;
  type: 'import' | 'violation' | 'compliant' | 'review';
  title: string;
  message: string;
}> = [];

// Violations tracking - store all detected violations
const violationsList: Array<{
  productId: string;
  sku: string;
  title: string;
  url: string;
  analysis: string;
  timestamp: Date;
}> = [];

// Function to escalate violations to needs-attention agent
async function escalateViolationToNeedsAttention(violation: {
  title: string;
  productId?: string;
  sku?: string;
  reasoning: string;
  productUrl?: string;
}) {
  try {
    console.log(`🚨 Escalating violation to needs-attention agent: ${violation.sku || violation.title}`);

    const response = await fetch('http://localhost:9886/api/webhook/task', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        title: `🚨 URGENT: Legal Violation - ${violation.sku || violation.title}`,
        description: `SETTLEMENT AGREEMENT VIOLATION DETECTED

Product: ${violation.title}
SKU: ${violation.sku || 'Unknown'}
Product ID: ${violation.productId || 'Unknown'}

VIOLATION DETAILS:
${violation.reasoning}

REQUIRED ACTIONS:
1. Immediately unpublish product from store
2. Review product images and descriptions
3. Contact legal counsel if needed
4. Document the violation in legal records

Product URL: ${violation.productUrl || `https://designer-laboratory-sandbox.myshopify.com/admin/products/${violation.productId}`}`,
        priority: 'critical',
        source: 'legal',
        metadata: {
          productId: violation.productId,
          sku: violation.sku,
          violationType: 'settlement-agreement',
          reasoning: violation.reasoning,
          agentPort: 9878,
          url: violation.productUrl || `https://designer-laboratory-sandbox.myshopify.com/admin/products/${violation.productId}`
        },
        assignedAgent: 'needs-attention'
      })
    });

    if (response.ok) {
      const result = await response.json();
      console.log(`✅ Violation escalated to needs-attention: ${result.taskId}`);
    } else {
      console.error(`❌ Failed to escalate violation: ${response.statusText}`);
    }
  } catch (error) {
    console.error(`❌ Error escalating violation: ${error}`);
  }
}

app.use(express.json());
app.use(cookieParser());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));

// Add inter-agent chat widget (disabled - ESM incompatibility)
// app.use(chatMiddleware({
//   agentId: 'agent-legal',
//   agentName: 'Legal Team',
//   port: 9878,
//   category: 'agent'
// }));


// Session configuration
app.use(
  session({
    secret: 'dw-legal-team-secret-key-2025',
    resave: false,
    saveUninitialized: false,
    cookie: {
      secure: false,
      httpOnly: true,
      maxAge: 24 * 60 * 60 * 1000, // 24 hours
    },
  })
);

// Extend session type
declare module 'express-session' {
  interface SessionData {
    authenticated: boolean;
    captchaText: string;
  }
}

// Old requireAuth removed - using requireGlobalAuth middleware (line 47)

// Settlement criteria reference
const SETTLEMENT_AGREEMENT = {
  partA: {
    description: 'Prohibited Design Pattern',
    criteria: [
      'Repeating patterns with directional variation amongst leaves/palm fronds',
      'Open space between leaves',
      'More than one ink color'
    ],
    requirement: 'ALL three conditions must be present'
  },
  partB: {
    description: 'Prohibited Specific Elements',
    criteria: [
      'Bananas (FRUIT) or banana pods (NOT leaves - banana leaves are OK)',
      'Grapes (fruit/clusters)',
      'Birds',
      'Butterflies'
    ],
    requirement: 'ANY one of these elements'
  },
  acceptable: {
    description: 'Acceptable Tropical Design Elements',
    criteria: [
      'Tree trunks',
      'Clearly represented branches',
      'Fruit or animal elements (EXCEPT prohibited ones)'
    ],
    requirement: 'At least ONE must be present for tropical designs'
  },
  violation: 'BOTH Part A (all conditions) AND Part B (any element) must be present'
};

// Old login/logout/captcha routes removed - handled by global auth server

// Main HTML interface (protected by global auth)
app.get('/', (req, res) => {
  res.send(`
<!DOCTYPE html>
<html>
<head>
  <title>DW Legal Team - Settlement Compliance Monitor</title>
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
      color: #e0e0e0;
      padding: 20px;
      min-height: 100vh;
    }
    .header {
      background: linear-gradient(135deg, #8b0000 0%, #dc143c 100%);
      padding: 30px;
      border-radius: 12px;
      margin-bottom: 30px;
      box-shadow: 0 8px 32px rgba(220, 20, 60, 0.3);
    }
    .header h1 {
      color: white;
      font-size: 2.5em;
      margin-bottom: 10px;
      text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
    }
    .header .subtitle {
      color: #ffe6e6;
      font-size: 1.2em;
      font-weight: 300;
    }
    .priority-badge {
      display: inline-block;
      background: #ff0000;
      color: white;
      padding: 8px 16px;
      border-radius: 20px;
      font-weight: bold;
      margin-top: 15px;
      font-size: 0.9em;
      letter-spacing: 1px;
      animation: pulse 2s infinite;
    }
    @keyframes pulse {
      0%, 100% { opacity: 1; }
      50% { opacity: 0.7; }
    }
    .stats-grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
      gap: 20px;
      margin-bottom: 30px;
    }
    .stat-card {
      background: rgba(255, 255, 255, 0.05);
      border: 1px solid rgba(255, 255, 255, 0.1);
      padding: 20px;
      border-radius: 12px;
      backdrop-filter: blur(10px);
    }
    .stat-card h3 {
      color: #888;
      font-size: 0.9em;
      text-transform: uppercase;
      letter-spacing: 1px;
      margin-bottom: 10px;
    }
    .stat-card .value {
      font-size: 2.5em;
      font-weight: bold;
      color: #fff;
    }
    .stat-card.violations .value {
      color: #ff4444;
    }
    .stat-card.compliant .value {
      color: #4CAF50;
    }
    .stat-card.review .value {
      color: #FFA500;
    }
    .settlement-section {
      background: rgba(255, 255, 255, 0.05);
      border: 2px solid rgba(220, 20, 60, 0.5);
      padding: 30px;
      border-radius: 12px;
      margin-bottom: 30px;
      backdrop-filter: blur(10px);
    }
    .settlement-section h2 {
      color: #ff6b6b;
      margin-bottom: 20px;
      font-size: 1.8em;
      border-bottom: 2px solid rgba(220, 20, 60, 0.3);
      padding-bottom: 10px;
    }
    .criteria-box {
      background: rgba(0, 0, 0, 0.3);
      padding: 20px;
      border-radius: 8px;
      margin-bottom: 20px;
      border-left: 4px solid #dc143c;
    }
    .criteria-box h3 {
      color: #ff8888;
      margin-bottom: 15px;
      font-size: 1.3em;
    }
    .criteria-box ul {
      list-style: none;
      padding: 0;
    }
    .criteria-box li {
      padding: 10px 0;
      border-bottom: 1px solid rgba(255, 255, 255, 0.1);
      color: #ccc;
    }
    .criteria-box li:last-child {
      border-bottom: none;
    }
    .criteria-box .requirement {
      background: rgba(220, 20, 60, 0.2);
      padding: 10px;
      border-radius: 6px;
      margin-top: 15px;
      font-weight: bold;
      color: #ff9999;
    }
    .violation-rule {
      background: rgba(255, 0, 0, 0.2);
      border: 2px solid #ff0000;
      padding: 20px;
      border-radius: 8px;
      margin-top: 20px;
      font-size: 1.1em;
      font-weight: bold;
      color: #ffcccc;
      text-align: center;
    }
    .action-buttons {
      display: flex;
      gap: 15px;
      flex-wrap: wrap;
      margin-bottom: 30px;
    }
    button {
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      color: white;
      border: none;
      padding: 15px 30px;
      border-radius: 8px;
      font-size: 1em;
      cursor: pointer;
      transition: all 0.3s;
      font-weight: 600;
      box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
    }
    button:hover {
      transform: translateY(-2px);
      box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
    }
    button:active {
      transform: translateY(0);
    }
    button.scan {
      background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
    }
    button.review-tool {
      background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
    }
    .log-section {
      background: rgba(0, 0, 0, 0.4);
      padding: 20px;
      border-radius: 12px;
      margin-top: 30px;
      border: 1px solid rgba(255, 255, 255, 0.1);
    }
    .log-section h2 {
      color: #fff;
      margin-bottom: 15px;
      font-size: 1.5em;
    }
    .log-entry {
      padding: 10px;
      margin: 5px 0;
      border-radius: 6px;
      font-family: 'Courier New', monospace;
      font-size: 0.9em;
    }
    .log-entry.violation {
      background: rgba(255, 68, 68, 0.2);
      border-left: 4px solid #ff4444;
      color: #ff9999;
    }
    .log-entry.compliant {
      background: rgba(76, 175, 80, 0.2);
      border-left: 4px solid #4CAF50;
      color: #a5d6a7;
    }
    .log-entry.info {
      background: rgba(100, 100, 100, 0.2);
      border-left: 4px solid #888;
      color: #ccc;
    }
    .last-violation {
      background: rgba(255, 0, 0, 0.15);
      padding: 20px;
      border-radius: 8px;
      margin-top: 20px;
      border: 2px solid rgba(255, 0, 0, 0.3);
    }
    .last-violation h3 {
      color: #ff6666;
      margin-bottom: 10px;
    }
    .last-violation p {
      color: #ffcccc;
      margin: 5px 0;
    }
    .url-checker-section {
      background: rgba(255, 255, 255, 0.05);
      border: 2px solid rgba(102, 126, 234, 0.5);
      padding: 25px;
      border-radius: 12px;
      margin-bottom: 30px;
      backdrop-filter: blur(10px);
    }
    .url-checker-section h2 {
      color: #8888ff;
      margin-bottom: 20px;
      font-size: 1.6em;
    }
    .url-input-form {
      display: flex;
      gap: 15px;
      margin-bottom: 20px;
    }
    .url-input-form input {
      flex: 1;
      padding: 15px;
      border: 2px solid rgba(102, 126, 234, 0.5);
      border-radius: 8px;
      background: rgba(0, 0, 0, 0.3);
      color: #fff;
      font-size: 1em;
    }
    .url-input-form input:focus {
      outline: none;
      border-color: #667eea;
      box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
    }
    .url-input-form button {
      padding: 15px 40px;
      white-space: nowrap;
    }
    .url-result {
      background: rgba(0, 0, 0, 0.4);
      padding: 20px;
      border-radius: 8px;
      border-left: 4px solid #667eea;
      display: none;
    }
    .url-result.pass {
      border-left-color: #4CAF50;
      background: rgba(76, 175, 80, 0.1);
    }
    .url-result.violation {
      border-left-color: #ff4444;
      background: rgba(255, 68, 68, 0.1);
    }
    .url-result.checking {
      border-left-color: #FFA500;
      background: rgba(255, 165, 0, 0.1);
    }
    .url-result h3 {
      margin-bottom: 15px;
      font-size: 1.3em;
    }
    .url-result pre {
      white-space: pre-wrap;
      word-wrap: break-word;
      color: #ccc;
      line-height: 1.6;
    }

    /* Hooks Panel */
    .hooks-panel {
      background: linear-gradient(135deg, #2d1b47 0%, #1a0f2e 100%);
      padding: 20px;
      border-radius: 15px;
      box-shadow: 0 5px 20px rgba(0,0,0,0.3);
      margin: 20px 0;
      border: 1px solid rgba(255,230,230,0.1);
    }
    .hooks-panel h3 {
      color: #ffe6e6;
      font-size: 0.95em;
      text-transform: uppercase;
      margin-bottom: 15px;
      font-weight: 700;
    }
    .hook-btn {
      width: 100%;
      padding: 12px 16px;
      margin-bottom: 10px;
      background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
      color: white;
      border: none;
      border-radius: 10px;
      cursor: pointer;
      font-weight: 600;
      font-size: 0.9em;
      transition: all 0.3s;
      text-align: left;
      display: flex;
      align-items: center;
      gap: 8px;
    }
    .hook-btn:hover {
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3);
    }
    .hook-btn:active {
      transform: translateY(0);
    }
    .hook-btn:disabled {
      opacity: 0.6;
      cursor: not-allowed;
      transform: none;
    }
    .hook-btn.fix {
      background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
    }
    .hook-btn.monitor {
      background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
    }

    /* Communication Modal Styles */
    .modal { display: none; position: fixed; z-index: 10000; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); overflow: auto; }
    .modal.show { display: block; }
    .modal-content { background-color: white; margin: 5% auto; padding: 0; border-radius: 15px; width: 90%; max-width: 600px; box-shadow: 0 10px 40px rgba(0,0,0,0.3); animation: modalSlideIn 0.3s ease-out; }
    @keyframes modalSlideIn { from { transform: translateY(-50px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
    .modal-header { background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); color: white; padding: 20px 25px; border-radius: 15px 15px 0 0; display: flex; justify-content: space-between; align-items: center; }
    .modal-header h2 { margin: 0; font-size: 1.3em; }
    .modal-close { background: none; border: none; color: white; font-size: 1.8em; cursor: pointer; padding: 0; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; border-radius: 50%; transition: background 0.2s; }
    .modal-close:hover { background: rgba(255,255,255,0.2); }
    .modal-body { padding: 25px; }
    .form-group { margin-bottom: 20px; }
    .form-group label { display: block; color: #333; font-weight: 600; margin-bottom: 8px; font-size: 0.95em; }
    .form-group input, .form-group textarea, .form-group select { width: 100%; padding: 12px; border: 2px solid #e0e0e0; border-radius: 8px; font-size: 0.95em; font-family: inherit; transition: border-color 0.2s; }
    .form-group input:focus, .form-group textarea:focus, .form-group select:focus { outline: none; border-color: #e74c3c; }
    .form-group textarea { min-height: 120px; resize: vertical; }
    .modal-footer { padding: 20px 25px; background: #f8f9fa; border-radius: 0 0 15px 15px; display: flex; gap: 10px; justify-content: flex-end; }
    .modal-btn { padding: 10px 24px; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: all 0.2s; font-size: 0.95em; }
    .modal-btn-primary { background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); color: white; }
    .modal-btn-primary:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3); }
    .modal-btn-primary:disabled { opacity: 0.5; cursor: not-allowed; }
    .modal-btn-secondary { background: white; color: #666; border: 2px solid #e0e0e0; }
    .modal-btn-secondary:hover { background: #f0f0f0; }
    @media (max-width: 768px) { .modal-content { width: 95%; margin: 10% auto; } }
  </style>
</head>
<body style="padding: 20px;">
  ${getUniversalHeader('Legal Team', PORT, 5)}

  <div class="header" style="margin-top: 20px;">
    <h1>⚖️ DW Legal Team</h1>
    <div class="subtitle">Settlement Compliance Monitor</div>
    <div class="priority-badge">🚨 PRIORITY #1: SETTLEMENT AGREEMENT</div>
    <div style="text-align: right; margin-top: 15px;">
      <a href="/logout" style="color: #ffe6e6; text-decoration: none; padding: 8px 16px; background: rgba(0,0,0,0.3); border-radius: 6px; font-size: 0.9em;">Logout</a>
    </div>
  </div>

  <!-- System Hooks Panel -->
  <div class="hooks-panel">
    <h3>System Tools</h3>
    <button class="hook-btn" onclick="runHook('service-health-check', 'check')">
      <span>🏥</span> Health Check
    </button>
    <button class="hook-btn fix" onclick="runHook('service-health-check', 'fix')">
      <span>🔧</span> Auto-Fix
    </button>
    <button class="hook-btn monitor" onclick="runHook('agent-health-monitor')">
      <span>👥</span> Monitor Agents
    </button>
  </div>

  <!-- Communication Panel -->
  <div class="hooks-panel">
    <h3>📧 Communication</h3>
    <button class="hook-btn" onclick="openEmailModal()">
      <span>📧</span> Send Email
    </button>
    <button class="hook-btn" onclick="openSlackModal()">
      <span>💬</span> Post to Slack
    </button>
  </div>

  <div id="violationsList" class="violations-alert" style="display: none; background: rgba(255, 0, 0, 0.2); border: 4px solid #ff0000; padding: 30px; border-radius: 15px; margin-bottom: 25px;">
    <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
      <h2 style="color: #ff0000; font-size: 2.2em;">🚨 SETTLEMENT VIOLATIONS</h2>
      <div style="display: flex; gap: 10px;">
        <select id="violationFilter" onchange="loadLiveViolations()" style="padding: 8px 16px; border-radius: 8px; background: rgba(0,0,0,0.5); color: white; border: 1px solid #666;">
          <option value="all">All Violations</option>
          <option value="open" selected>Open</option>
          <option value="resolved">Resolved</option>
        </select>
        <button onclick="reportToCFO()" style="background: linear-gradient(135deg, #e74c3c, #c0392b); color: white; border: none; padding: 10px 20px; border-radius: 8px; cursor: pointer; font-weight: bold;">📊 Report to CFO</button>
      </div>
    </div>
    <div id="violationsSummary" style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 20px;"></div>
    <div id="violationsContent"></div>
  </div>

  <div class="settlement-section" style="background: rgba(220, 20, 60, 0.15); border: 3px solid #dc143c;">
    <h2>📋 Settlement Agreement - Quick Reference</h2>

    <div class="violation-rule" style="margin-bottom: 20px;">
      ⚠️ VIOLATION OCCURS WHEN: BOTH Part A (all conditions) AND Part B (any element) are present
    </div>

    <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px;">
      <div class="criteria-box">
        <h3>Part A: Prohibited Design Pattern</h3>
        <ul>
          <li>✓ Repeating patterns with directional variation amongst leaves/palm fronds</li>
          <li>✓ Open space between leaves</li>
          <li>✓ More than one ink color</li>
        </ul>
        <div class="requirement">ALL three conditions must be present</div>
      </div>

      <div class="criteria-box">
        <h3>Part B: Prohibited Specific Elements</h3>
        <ul>
          <li>🚫 Bananas (FRUIT) or banana pods - <strong style="color: #90EE90;">NOTE: Banana LEAVES are OK!</strong></li>
          <li>🚫 Grapes (fruit/clusters)</li>
          <li>🚫 Birds</li>
          <li>🚫 Butterflies</li>
        </ul>
        <div class="requirement">ANY one of these elements</div>
      </div>
    </div>

    <div class="criteria-box" style="margin-top: 20px; border-left-color: #4CAF50;">
      <h3 style="color: #90EE90;">✅ Acceptable Tropical Design Elements</h3>
      <ul>
        <li>✓ Tree trunks</li>
        <li>✓ Clearly represented branches</li>
        <li>✓ Fruit or animal elements (EXCEPT prohibited ones)</li>
      </ul>
      <div class="requirement" style="background: rgba(76, 175, 80, 0.2); color: #a5d6a7;">At least ONE must be present for tropical designs</div>
    </div>
  </div>

  <div class="url-checker-section">
    <h2>🔍 Quick URL Compliance Check</h2>
    <form class="url-input-form" onsubmit="checkURL(event)">
      <input type="url" id="urlInput" placeholder="Enter product URL to check for settlement compliance..." required>
      <button type="submit">Check Now</button>
    </form>
    <div id="urlResult" class="url-result"></div>
  </div>

  <div class="stats-grid">
    <div class="stat-card">
      <h3>Imports Monitored</h3>
      <div class="value" id="importsMonitored">0</div>
    </div>
    <div class="stat-card violations">
      <h3>Violations</h3>
      <div class="value" id="violations">0</div>
    </div>
    <div class="stat-card compliant">
      <h3>Compliant</h3>
      <div class="value" id="compliant">0</div>
    </div>
    <div class="stat-card review">
      <h3>Needs Review</h3>
      <div class="value" id="needsReview">0</div>
    </div>
  </div>

  <div id="lastImport" class="last-violation" style="display:none; background: rgba(0, 100, 255, 0.15); border-color: rgba(0, 100, 255, 0.3);">
    <h3>📦 Most Recent Import</h3>
    <p id="importTitle"></p>
    <p id="importStatus"></p>
    <p id="importTime"></p>
  </div>

  <div class="settlement-section">
    <h2>📋 Settlement Agreement Criteria</h2>

    <div class="criteria-box">
      <h3>Part A: Prohibited Design Pattern</h3>
      <ul>
        <li>✓ Repeating patterns with directional variation amongst leaves/palm fronds</li>
        <li>✓ Open space between leaves</li>
        <li>✓ More than one ink color</li>
      </ul>
      <div class="requirement">ALL three conditions must be present</div>
    </div>

    <div class="criteria-box">
      <h3>Part B: Prohibited Specific Elements</h3>
      <ul>
        <li>🚫 Bananas (FRUIT) or banana pods - <strong style="color: #90EE90;">NOTE: Banana LEAVES are OK!</strong></li>
        <li>🚫 Grapes (fruit/clusters)</li>
        <li>🚫 Birds</li>
        <li>🚫 Butterflies</li>
      </ul>
      <div class="requirement">ANY one of these elements</div>
    </div>

    <div class="criteria-box">
      <h3>✅ Acceptable Tropical Design Elements</h3>
      <ul>
        <li>✓ Tree trunks</li>
        <li>✓ Clearly represented branches</li>
        <li>✓ Fruit or animal elements (EXCEPT prohibited ones)</li>
      </ul>
      <div class="requirement">At least ONE must be present for tropical designs</div>
    </div>

    <div class="violation-rule">
      ⚠️ VIOLATION OCCURS WHEN: BOTH Part A (all conditions) AND Part B (any element) are present
    </div>
  </div>

  <div class="settlement-section" style="background: rgba(220, 20, 60, 0.1); border: 2px solid #dc143c;">
    <h2>🔍 Search for Settlement Violations</h2>

    <div class="criteria-box">
      <h3>🚫 Search by Prohibited Elements (Part B)</h3>
      <div class="action-buttons" style="grid-template-columns: repeat(4, 1fr);">
        <button class="scan" onclick="searchByKeyword('banana')">🍌 Bananas</button>
        <button class="scan" onclick="searchByKeyword('grape')">🍇 Grapes</button>
        <button class="scan" onclick="searchByKeyword('bird')">🦜 Birds</button>
        <button class="scan" onclick="searchByKeyword('butterfly')">🦋 Butterflies</button>
      </div>
    </div>

    <div class="criteria-box">
      <h3>🌴 Search by Tropical Keywords</h3>
      <div class="action-buttons" style="grid-template-columns: repeat(4, 1fr);">
        <button class="scan" onclick="searchByKeyword('palm')">🌴 Palm</button>
        <button class="scan" onclick="searchByKeyword('tropical')">🏝️ Tropical</button>
        <button class="scan" onclick="searchByKeyword('leaf')">🍃 Leaf</button>
        <button class="scan" onclick="searchByKeyword('frond')">🌿 Frond</button>
        <button class="scan" onclick="searchByKeyword('jungle')">🌳 Jungle</button>
        <button class="scan" onclick="searchByKeyword('exotic')">🦎 Exotic</button>
        <button class="scan" onclick="searchByKeyword('botanical')">🌺 Botanical</button>
        <button class="scan" onclick="searchByKeyword('paradise')">🦚 Paradise</button>
      </div>
    </div>

    <div class="criteria-box">
      <h3>⚠️ Search by Fruit & Nature Keywords</h3>
      <div class="action-buttons" style="grid-template-columns: repeat(4, 1fr);">
        <button class="scan" onclick="searchByKeyword('fruit')">🍎 Fruit</button>
        <button class="scan" onclick="searchByKeyword('flower')">🌸 Flower</button>
        <button class="scan" onclick="searchByKeyword('blossom')">🌼 Blossom</button>
        <button class="scan" onclick="searchByKeyword('vine')">🍇 Vine</button>
      </div>
    </div>
  </div>

  <div class="action-buttons">
    <button class="scan" onclick="scanCatalog()">🔍 Scan Entire Catalog</button>
    <button class="scan" onclick="scanNewProducts()">🆕 Scan New Products (24h)</button>
    <button class="scan" onclick="scanTagged()">🏷️ Scan SETTLEMENT Tagged</button>
    <button class="review-tool" onclick="openReviewTool()">📊 Open Settlement Review Tool</button>
  </div>

  <div id="search-results" style="margin-top: 30px;"></div>

  <div id="lastViolation" class="last-violation" style="display:none;">
    <h3>🚨 Most Recent Violation</h3>
    <p id="violationTitle"></p>
    <p id="violationId"></p>
    <p id="violationTime"></p>
  </div>

  <div class="log-section">
    <h2>📝 Activity Log</h2>
    <div id="logs"></div>
  </div>

  <script>
    function updateStats() {
      fetch('/api/stats')
        .then(r => r.json())
        .then(data => {
          document.getElementById('importsMonitored').textContent = data.importsMonitored;
          document.getElementById('violations').textContent = data.violations;
          document.getElementById('compliant').textContent = data.compliant;
          document.getElementById('needsReview').textContent = data.needsReview;

          if (data.lastImport) {
            document.getElementById('lastImport').style.display = 'block';
            document.getElementById('importTitle').textContent = 'Product: ' + data.lastImport.title;
            document.getElementById('importStatus').textContent = 'Status: ' + data.lastImport.status;
            document.getElementById('importTime').textContent = 'Time: ' + new Date(data.lastImport.timestamp).toLocaleString();
          }
        });

      // Load live violations from DB
      loadLiveViolations();
    }

    function loadLiveViolations() {
      const filter = document.getElementById('violationFilter').value;
      fetch('/api/violations?status=' + filter + '&limit=50')
        .then(r => r.json())
        .then(violations => {
          const violationsList = document.getElementById('violationsList');
          const violationsContent = document.getElementById('violationsContent');

          // Always show the panel
          violationsList.style.display = 'block';

          // Load summary stats
          fetch('/api/violations/summary')
            .then(r => r.json())
            .then(summary => {
              document.getElementById('violationsSummary').innerHTML =
                '<div style="background: rgba(255,0,0,0.2); padding: 12px; border-radius: 8px; text-align: center;"><div style="font-size: 24px; font-weight: bold; color: #ff4444;">' + (summary.open_count || 0) + '</div><div style="font-size: 11px; color: #ffaaaa;">OPEN</div></div>' +
                '<div style="background: rgba(76,175,80,0.2); padding: 12px; border-radius: 8px; text-align: center;"><div style="font-size: 24px; font-weight: bold; color: #4CAF50;">' + (summary.resolved_count || 0) + '</div><div style="font-size: 11px; color: #a5d6a7;">RESOLVED</div></div>' +
                '<div style="background: rgba(255,165,0,0.2); padding: 12px; border-radius: 8px; text-align: center;"><div style="font-size: 24px; font-weight: bold; color: #FFA500;">' + (summary.high_risk || 0) + '</div><div style="font-size: 11px; color: #ffcc80;">HIGH RISK</div></div>' +
                '<div style="background: rgba(33,150,243,0.2); padding: 12px; border-radius: 8px; text-align: center;"><div style="font-size: 24px; font-weight: bold; color: #2196F3;">' + (summary.reported_to_cfo || 0) + '</div><div style="font-size: 11px; color: #90caf9;">CFO REPORTED</div></div>';
            });

          if (violations.length > 0) {
            violationsContent.innerHTML = violations.map(function(v) {
              var statusColor = v.status === 'resolved' ? '#4CAF50' : '#ff0000';
              var statusBadge = v.status === 'resolved'
                ? '<span style="background: #4CAF50; color: white; padding: 3px 10px; border-radius: 12px; font-size: 0.75em;">RESOLVED</span>'
                : '<span style="background: #ff0000; color: white; padding: 3px 10px; border-radius: 12px; font-size: 0.75em;">OPEN</span>';
              var cfoFlag = v.reportedToCfo
                ? '<span style="background: #2196F3; color: white; padding: 3px 10px; border-radius: 12px; font-size: 0.75em; margin-left: 5px;">CFO NOTIFIED</span>'
                : '';
              var dateStr = new Date(v.timestamp).toLocaleString();

              return '<div style="background: white; border-left: 6px solid ' + statusColor + '; padding: 20px; margin-bottom: 15px; border-radius: 8px; color: #333;">' +
                '<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">' +
                  '<h3 style="color: ' + statusColor + '; margin: 0;">' + (v.title || 'Unknown') + '</h3>' +
                  '<div>' + statusBadge + cfoFlag + '</div>' +
                '</div>' +
                '<div style="display: grid; grid-template-columns: 1fr 1fr 1fr 1fr; gap: 10px; margin-bottom: 10px; font-size: 0.85em;">' +
                  '<div><strong>SKU:</strong> ' + (v.sku || 'N/A') + '</div>' +
                  '<div><strong>Risk:</strong> <span style="color: ' + (v.riskLevel === 'HIGH' ? 'red' : 'orange') + '; font-weight: bold;">' + (v.riskLevel || 'HIGH') + '</span></div>' +
                  '<div><strong>Vendor:</strong> ' + (v.vendor || 'Unknown') + '</div>' +
                  '<div><strong>Detected:</strong> ' + dateStr + '</div>' +
                '</div>' +
                (v.imageUrl ? '<img src="' + v.imageUrl + '" style="max-width: 150px; border-radius: 6px; float: right; margin-left: 15px;" onerror="this.style.display=\'none\'" />' : '') +
                '<div style="background: #fff8f8; padding: 15px; border-radius: 6px; margin: 10px 0; font-size: 0.85em; white-space: pre-wrap; max-height: 200px; overflow-y: auto;">' + (v.analysis || '') + '</div>' +
                '<div style="display: flex; gap: 10px; align-items: center;">' +
                  '<a href="' + (v.url || '#') + '" target="_blank" style="display: inline-block; background: #dc143c; color: white; padding: 8px 16px; border-radius: 6px; text-decoration: none; font-weight: bold; font-size: 0.9em;">View in Shopify</a>' +
                  (v.status !== 'resolved' ? '<button onclick="resolveViolation(' + v.id + ')" style="background: #4CAF50; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: bold; font-size: 0.9em;">Mark Resolved</button>' : '') +
                '</div>' +
              '</div>';
            }).join('');
          } else {
            violationsContent.innerHTML = '<div style="text-align: center; padding: 40px; color: #aaa;">No violations found for this filter.</div>';
          }
        });
    }

    function reportToCFO() {
      if (!confirm('Send all open violations to CFO Dashboard?')) return;
      fetch('/api/report-to-cfo', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) })
        .then(r => r.json())
        .then(data => {
          if (data.success) {
            alert('Reported ' + data.reported + ' violations to CFO Dashboard');
            loadLiveViolations();
          } else {
            alert(data.message || 'No unreported violations');
          }
        })
        .catch(err => alert('Error: ' + err.message));
    }

    function resolveViolation(id) {
      var notes = prompt('Resolution notes (optional):');
      fetch('/api/violations/' + id + '/resolve', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ resolution_notes: notes || '', resolved_by: 'admin' })
      })
      .then(r => r.json())
      .then(data => {
        if (data.success) loadLiveViolations();
      });
    }

    function addLog(message, type = 'info') {
      const logsDiv = document.getElementById('logs');
      const entry = document.createElement('div');
      entry.className = 'log-entry ' + type;
      entry.textContent = new Date().toLocaleTimeString() + ' - ' + message;
      logsDiv.insertBefore(entry, logsDiv.firstChild);

      // Keep only last 50 entries
      while (logsDiv.children.length > 50) {
        logsDiv.removeChild(logsDiv.lastChild);
      }
    }

    function searchByKeyword(keyword) {
      addLog(\`Searching for products containing "\${keyword}"...\`, 'info');
      const resultsDiv = document.getElementById('search-results');
      resultsDiv.innerHTML = '<div style="color: #FFA500; text-align: center; padding: 40px;">⏳ Searching...</div>';

      fetch(\`/api/search/keyword?q=\${encodeURIComponent(keyword)}\`, {
        credentials: 'same-origin'
      })
        .then(r => {
          if (!r.ok) {
            throw new Error(\`HTTP \${r.status}: \${r.statusText}\`);
          }
          return r.json();
        })
        .then(data => {
          if (data.error) {
            throw new Error(data.error);
          }
          if (data.products && data.products.length > 0) {
            addLog(\`Found \${data.products.length} products with "\${keyword}" - Analyzing for violations...\`, 'success');
            showSearchResults(keyword, data.products);
          } else {
            addLog(\`No products found containing "\${keyword}"\`, 'info');
            resultsDiv.innerHTML = '<div style="color: #aaa; text-align: center; padding: 40px;">No products found</div>';
          }
        })
        .catch(err => {
          addLog(\`Error searching for "\${keyword}": \${err.message}\`, 'error');
          resultsDiv.innerHTML = '<div style="color: #dc143c; text-align: center; padding: 40px;">Error: ' + err.message + '</div>';
        });
    }

    function showSearchResults(keyword, products) {
      const resultsDiv = document.getElementById('search-results');
      resultsDiv.innerHTML = \`
        <h2 style="color: #dc143c; margin-bottom: 20px;">🔍 "\` + keyword + \`" - Found \` + products.length + \` Products</h2>
        <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;">
          \` + products.map(p => \`
            <div id="product-\` + p.id + \`" style="position: relative; background: rgba(255,255,255,0.05); padding: 20px; border-radius: 12px; border-left: 4px solid #dc143c;">
              <div style="position: absolute; top: 10px; right: 10px; z-index: 10;">
                <span style="background: \` + (p.status === 'active' ? '#4CAF50' : '#FFA500') + \`; color: white; padding: 4px 12px; border-radius: 20px; font-size: 0.75em; font-weight: bold;">\` + (p.status === 'active' ? '🟢 ACTIVE' : '🟡 DRAFT') + \`</span>
              </div>
              \` + (p.image ? '<img src="' + p.image + '" alt="' + p.title + '" style="width: 100%; height: 200px; object-fit: cover; border-radius: 8px; margin-bottom: 15px;">' : '<div style="width: 100%; height: 200px; background: rgba(255,255,255,0.1); border-radius: 8px; display: flex; align-items: center; justify-content: center; color: #666; margin-bottom: 15px;">No Image</div>') + \`
              <h3 style="color: #fff; margin: 0 0 10px 0; font-size: 1.1em;">\` + p.title + \`</h3>
              <div style="color: #aaa; font-size: 0.85em; margin-bottom: 10px;">
                <div>SKU: \` + (p.sku || 'N/A') + \`</div>
                <div>ID: \` + p.id + \`</div>
                \` + (p.vendor ? '<div>Vendor: ' + p.vendor + '</div>' : '') + \`
              </div>
              <div id="compliance-\` + p.id + \`" style="margin: 10px 0;">
                <div style="color: #FFA500; font-size: 0.85em;">⏳ Analyzing...</div>
              </div>
              <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 10px;">
                <a href="https://admin.shopify.com/store/designer-laboratory-sandbox/products/\` + p.id + \`" target="_blank" style="background: #4CAF50; color: white; padding: 10px; border-radius: 6px; text-decoration: none; font-size: 0.85em; text-align: center; font-weight: bold;">📝 Shopify</a>
                <button onclick="setToDraft('\` + p.id + \`')" style="background: #dc143c; color: white; padding: 10px; border-radius: 6px; border: none; font-size: 0.85em; cursor: pointer; font-weight: bold;">⚠️ Set Draft</button>
              </div>
            </div>
          \`).join('') + \`
        </div>
      \`;

      // Auto-check compliance with AI for all products
      products.forEach(p => {
        if (p.image) {
          checkProductWithImage(p.image, p.title, p.tags, p.id);
        } else if (p.online_store_url) {
          checkProductCompliance(p.online_store_url, p.id);
        }
      });
    }

    function formatAnalysis(text) {
      // Format the analysis to clearly separate CRITERIA SET A and SET B
      let formatted = text;

      // Add visual separators for the sections
      formatted = formatted.replace(/CRITERIA SET A:/gi, '<div style="margin-top: 10px; padding: 8px; background: rgba(255,255,255,0.05); border-radius: 4px;"><strong style="color: #FFD700;">📋 CRITERIA SET A (Pattern Features):</strong>');
      formatted = formatted.replace(/CRITERIA SET B:/gi, '</div><div style="margin-top: 8px; padding: 8px; background: rgba(255,255,255,0.05); border-radius: 4px;"><strong style="color: #FF6B6B;">🚫 CRITERIA SET B (Prohibited Elements):</strong>');
      formatted = formatted.replace(/Final answer:/gi, '</div><div style="margin-top: 10px; padding: 8px; border-top: 2px solid rgba(255,255,255,0.2);"><strong>Final answer:</strong>');

      return formatted;
    }

    function sortProductsToTop() {
      // Move all violation cards to the top
      const resultsContainer = document.querySelector('#search-results > div');
      if (!resultsContainer) return;

      const productCards = Array.from(resultsContainer.children);
      const violations = [];
      const compliant = [];

      productCards.forEach(card => {
        const complianceDiv = card.querySelector('[id^="compliance-"]');
        if (complianceDiv && complianceDiv.innerHTML.includes('🚨 SETTLEMENT VIOLATION')) {
          violations.push(card);
        } else {
          compliant.push(card);
        }
      });

      // Clear and re-add: violations first, then compliant
      resultsContainer.innerHTML = '';
      violations.forEach(card => resultsContainer.appendChild(card));
      compliant.forEach(card => resultsContainer.appendChild(card));
    }

    function checkProductWithImage(imageUrl, title, tags, productId) {
      const complianceDiv = document.getElementById(\`compliance-\${productId}\`);
      complianceDiv.innerHTML = '<div style="color: #FFA500; font-size: 0.85em;">⏳ AI analyzing image...</div>';

      fetch('/api/check-image', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ imageUrl, title, tags, productId })
      })
      .then(r => r.json())
      .then(data => {
        const verifiedBadge = data.cached ? '<div style="display: inline-block; background: #2196F3; color: white; padding: 4px 10px; border-radius: 12px; font-size: 0.75em; margin-left: 8px;">✓ VERIFIED</div>' : '';

        if (data.compliant === false) {
          complianceDiv.innerHTML = \`
            <div style="background: rgba(220, 20, 60, 0.2); border: 2px solid #dc143c; padding: 12px; border-radius: 6px;">
              <div><strong style="color: #ff6b6b;">🚨 SETTLEMENT VIOLATION</strong>\${verifiedBadge}</div>
              <div style="color: #ffaaaa; font-size: 0.85em; margin-top: 8px; line-height: 1.6;">
                \${formatAnalysis(data.analysis || data.reason || 'Violates settlement agreement')}
              </div>
            </div>
          \`;
          // Sort violations to top after marking
          setTimeout(sortProductsToTop, 100);
        } else {
          complianceDiv.innerHTML = \`
            <div style="background: rgba(76, 175, 80, 0.15); border: 1px solid #4CAF50; padding: 10px; border-radius: 6px;">
              <div><strong style="color: #90EE90; font-size: 0.85em;">✅ COMPLIANT</strong>\${verifiedBadge}</div>
              <div style="color: #aaa; font-size: 0.8em; margin-top: 4px; line-height: 1.6;">
                \${formatAnalysis(data.analysis || 'No settlement violations detected')}
              </div>
            </div>
          \`;
        }
      })
      .catch(err => {
        complianceDiv.innerHTML = '<div style="color: #dc143c; font-size: 0.85em;">Error: ' + err.message + '</div>';
      });
    }

    function checkProductCompliance(url, productId) {
      const complianceDiv = document.getElementById(\`compliance-\${productId}\`);
      complianceDiv.innerHTML = '<div style="color: #FFA500;">⏳ Analyzing for settlement violations...</div>';

      fetch('/api/check-url', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ url })
      })
      .then(r => r.json())
      .then(data => {
        if (data.compliant === false) {
          complianceDiv.innerHTML = \`
            <div style="background: rgba(220,20,60,0.2); border: 2px solid #dc143c; padding: 15px; border-radius: 8px; margin-top: 10px;">
              <div style="color: #dc143c; font-weight: bold; font-size: 1.1em; margin-bottom: 10px;">🚨 SETTLEMENT VIOLATION DETECTED</div>
              <div style="color: #fff; margin-bottom: 8px;"><strong>Reason:</strong> \${data.reason || 'Contains prohibited elements'}</div>
              \${data.analysis ? '<div style="color: #aaa; font-size: 0.9em; margin-top: 8px;">' + data.analysis + '</div>' : ''}
            </div>
          \`;
        } else {
          complianceDiv.innerHTML = \`
            <div style="background: rgba(76,175,80,0.2); border: 2px solid #4CAF50; padding: 15px; border-radius: 8px; margin-top: 10px;">
              <div style="color: #4CAF50; font-weight: bold;">✅ COMPLIANT</div>
              <div style="color: #aaa; font-size: 0.9em; margin-top: 5px;">\${data.reason || 'No settlement violations detected'}</div>
            </div>
          \`;
        }
      })
      .catch(err => {
        complianceDiv.innerHTML = \`<div style="color: #FFA500;">⚠️ Error: \${err.message}</div>\`;
      });
    }

    function scanCatalog() {
      addLog('Starting full catalog scan...', 'info');
      fetch('/api/scan/catalog', { method: 'POST' })
        .then(r => r.json())
        .then(data => {
          addLog('Catalog scan complete: ' + data.scanned + ' products scanned', 'info');
          updateStats();
        });
    }

    function scanNewProducts() {
      addLog('Scanning products from last 24 hours...', 'info');
      fetch('/api/scan/new', { method: 'POST' })
        .then(r => r.json())
        .then(data => {
          addLog('New products scan complete: ' + data.scanned + ' products scanned', 'info');
          updateStats();
        });
    }

    function scanTagged() {
      addLog('Scanning SETTLEMENT tagged products...', 'info');
      fetch('/api/scan/tagged', { method: 'POST' })
        .then(r => r.json())
        .then(data => {
          addLog('Tagged products scan complete: ' + data.scanned + ' products scanned', 'info');
          updateStats();
        });
    }

    function openReviewTool() {
      window.open('http://45.61.58.125:9877', '_blank');
    }

    async function setToDraft(productId) {
      if (!confirm('Set this product to DRAFT status? This will hide it from the store.')) {
        return;
      }

      try {
        const response = await fetch('/api/set-draft', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ productId })
        });

        const data = await response.json();

        if (data.success) {
          addLog(\`Product \${productId} set to DRAFT\`, 'success');
          alert('✅ Product set to DRAFT successfully!');
          // Refresh the card to show new status
          location.reload();
        } else {
          throw new Error(data.error || 'Failed to set draft');
        }
      } catch (error) {
        addLog(\`Error setting product to draft: \${error.message}\`, 'error');
        alert('❌ Error: ' + error.message);
      }
    }

    async function checkURL(event) {
      event.preventDefault();

      const urlInput = document.getElementById('urlInput');
      const resultDiv = document.getElementById('urlResult');
      const url = urlInput.value.trim();

      if (!url) return;

      // Show checking state
      resultDiv.className = 'url-result checking';
      resultDiv.style.display = 'block';
      resultDiv.innerHTML = '<h3>🔄 Checking URL...</h3><p>Scraping page and analyzing for settlement compliance...</p>';

      try {
        const response = await fetch('/api/check-url', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ url })
        });

        const data = await response.json();

        if (data.error) {
          resultDiv.className = 'url-result violation';
          resultDiv.innerHTML = '<h3>❌ Error</h3><pre>' + data.error + '</pre>';
          return;
        }

        if (data.status === 'PASS') {
          resultDiv.className = 'url-result pass';
          resultDiv.innerHTML = '<h3>✅ PASS - Compliant</h3><pre>' + data.analysis + '</pre>';
          addLog('URL check PASSED: ' + url, 'compliant');
        } else if (data.status === 'VIOLATION') {
          resultDiv.className = 'url-result violation';
          resultDiv.innerHTML = '<h3>🚨 VIOLATION - Settlement Issue Detected</h3><pre>' + data.analysis + '</pre>';
          addLog('URL check VIOLATION: ' + url, 'violation');
        } else {
          resultDiv.className = 'url-result';
          resultDiv.innerHTML = '<h3>⚠️ Needs Review</h3><pre>' + data.analysis + '</pre>';
          addLog('URL check needs review: ' + url, 'info');
        }
      } catch (error) {
        resultDiv.className = 'url-result violation';
        resultDiv.innerHTML = '<h3>❌ Error</h3><pre>Failed to check URL: ' + error.message + '</pre>';
      }
    }

    // Hook execution function
    async function runHook(hookName, action = '') {
      const btn = event.target.closest('.hook-btn');
      if (btn.disabled) return;

      btn.disabled = true;
      const originalText = btn.innerHTML;
      btn.innerHTML = '<span style="display:inline-block;width:12px;height:12px;border:2px solid rgba(255,255,255,0.3);border-radius:50%;border-top-color:white;animation:spin 0.6s linear infinite;"></span> Running...';

      try {
        const response = await fetch('/api/hooks/' + hookName, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ action })
        });

        const result = await response.json();

        if (result.success) {
          alert('Hook executed successfully!' + (result.output ? '\n\n' + result.output : ''));
          addLog(\`Hook executed: \${hookName} \${action}\`, 'info');
        } else {
          alert('Hook error: ' + (result.error || 'Unknown error'));
          addLog(\`Hook failed: \${hookName} - \${result.error}\`, 'error');
        }
      } catch (err) {
        console.error('Hook execution error:', err);
        alert('Error: ' + err.message);
        addLog(\`Hook error: \${hookName} - \${err.message}\`, 'error');
      } finally {
        btn.disabled = false;
        btn.innerHTML = originalText;
      }
    }

    // Update stats every 10 seconds
    setInterval(updateStats, 10000);
    updateStats();

    addLog('DW Legal Team initialized - Settlement compliance monitoring active', 'info');

    // Communication Modal Functions
    const MCP_API_URL = 'http://localhost:3001';
    const MCP_AUTH = btoa('admin:password123');
    function openEmailModal() { document.getElementById('emailModal').classList.add('show'); }
    function closeEmailModal() { document.getElementById('emailModal').classList.remove('show'); }
    function openSlackModal() { document.getElementById('slackModal').classList.add('show'); }
    function closeSlackModal() { document.getElementById('slackModal').classList.remove('show'); }
    async function sendEmail() {
      const to = document.getElementById('emailTo').value;
      const subject = document.getElementById('emailSubject').value;
      const body = document.getElementById('emailBody').value;
      if (!to || !subject || !body) { showToast('Please fill in all fields', 'error'); return; }
      const btn = document.getElementById('sendEmailBtn');
      btn.disabled = true; btn.textContent = 'Sending...';
      try {
        const response = await fetch(MCP_API_URL + '/api/gmail/send', {
          method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + MCP_AUTH },
          body: JSON.stringify({ to, subject, body })
        });
        const data = await response.json();
        if (data.success) { showToast('Email sent successfully!', 'success'); closeEmailModal(); document.getElementById('emailTo').value = ''; document.getElementById('emailSubject').value = ''; document.getElementById('emailBody').value = ''; }
        else { showToast('Failed to send email: ' + (data.error || 'Unknown error'), 'error'); }
      } catch (error) { showToast('Error sending email: ' + error.message, 'error'); }
      finally { btn.disabled = false; btn.textContent = 'Send Email'; }
    }
    async function sendSlackMessage() {
      const channel = document.getElementById('slackChannel').value;
      const text = document.getElementById('slackMessage').value;
      if (!channel || !text) { showToast('Please fill in all fields', 'error'); return; }
      const btn = document.getElementById('sendSlackBtn');
      btn.disabled = true; btn.textContent = 'Sending...';
      try {
        const response = await fetch(MCP_API_URL + '/api/slack/message', {
          method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Basic ' + MCP_AUTH },
          body: JSON.stringify({ channel, text })
        });
        const data = await response.json();
        if (data.success) { showToast('Message posted to Slack!', 'success'); closeSlackModal(); document.getElementById('slackChannel').value = ''; document.getElementById('slackMessage').value = ''; }
        else { showToast('Failed to post message: ' + (data.error || 'Unknown error'), 'error'); }
      } catch (error) { showToast('Error posting to Slack: ' + error.message, 'error'); }
      finally { btn.disabled = false; btn.textContent = 'Send Message'; }
    }
    window.onclick = function(event) { if (event.target.classList.contains('modal')) { event.target.classList.remove('show'); } }
  </script>

  <!-- Email Modal -->
  <div id="emailModal" class="modal">
    <div class="modal-content">
      <div class="modal-header"><h2>📧 Send Email</h2><button class="modal-close" onclick="closeEmailModal()">&times;</button></div>
      <div class="modal-body">
        <div class="form-group"><label for="emailTo">Recipient Email</label><input type="email" id="emailTo" placeholder="recipient@example.com" /></div>
        <div class="form-group"><label for="emailSubject">Subject</label><input type="text" id="emailSubject" placeholder="Email subject" /></div>
        <div class="form-group"><label for="emailBody">Message</label><textarea id="emailBody" placeholder="Your message here..."></textarea></div>
      </div>
      <div class="modal-footer">
        <button class="modal-btn modal-btn-secondary" onclick="closeEmailModal()">Cancel</button>
        <button class="modal-btn modal-btn-primary" id="sendEmailBtn" onclick="sendEmail()">Send Email</button>
      </div>
    </div>
  </div>

  <!-- Slack Modal -->
  <div id="slackModal" class="modal">
    <div class="modal-content">
      <div class="modal-header"><h2>💬 Post to Slack</h2><button class="modal-close" onclick="closeSlackModal()">&times;</button></div>
      <div class="modal-body">
        <div class="form-group"><label for="slackChannel">Channel</label><input type="text" id="slackChannel" placeholder="#general or @username" /></div>
        <div class="form-group"><label for="slackMessage">Message</label><textarea id="slackMessage" placeholder="Your message here..."></textarea></div>
      </div>
      <div class="modal-footer">
        <button class="modal-btn modal-btn-secondary" onclick="closeSlackModal()">Cancel</button>
        <button class="modal-btn modal-btn-primary" id="sendSlackBtn" onclick="sendSlackMessage()">Send Message</button>
      </div>
    </div>
  </div>

</body>
</html>
  `);
});

// API endpoints (protected)
app.get('/api/stats', (req, res) => {
  res.json(stats);
});

app.get('/api/activity', (req, res) => {
  // Return last 100 activity log entries
  res.json(activityLog.slice(-100).reverse());
});

app.get('/api/violations', async (req, res) => {
  // Return violations from PostgreSQL sorted by most recent first
  try {
    const status = (req.query.status as string) || 'all';
    const limit = parseInt(req.query.limit as string) || 100;
    const dbViolations = await loadViolationsFromDB(limit, status);
    // Also include in-memory violations not yet in DB
    const combined = dbViolations.map(v => ({
      productId: v.product_id || v.shopify_product_id,
      sku: v.sku,
      title: v.title,
      url: v.source_url,
      analysis: v.analysis,
      timestamp: v.detected_at,
      riskLevel: v.risk_level,
      status: v.status,
      vendor: v.vendor,
      imageUrl: v.image_url,
      reportedToCfo: v.reported_to_cfo,
      id: v.id
    }));
    res.json(combined);
  } catch (e: any) {
    // Fallback to in-memory
    res.json(violationsList.slice().reverse());
  }
});

// Report violations to CFO
app.post('/api/report-to-cfo', async (req, res) => {
  try {
    const { violationIds } = req.body;
    let violations;
    if (violationIds && violationIds.length > 0) {
      violations = await psqlQueryJSON(`SELECT * FROM legal_violations WHERE id IN (${violationIds.join(',')})`);
    } else {
      violations = await psqlQueryJSON(`SELECT * FROM legal_violations WHERE status = 'open' AND reported_to_cfo = false ORDER BY detected_at DESC`);
    }
    if (!violations || violations.length === 0) {
      return res.json({ success: false, message: 'No unreported violations to send' });
    }
    const success = await reportToCFO(violations);
    res.json({ success, reported: violations.length });
  } catch (e: any) {
    res.status(500).json({ error: e.message });
  }
});

// Resolve a violation
app.post('/api/violations/:id/resolve', async (req, res) => {
  try {
    const { id } = req.params;
    const { resolution_notes, resolved_by } = req.body;
    const notes = (resolution_notes || '').replace(/'/g, "''");
    const by = (resolved_by || 'admin').replace(/'/g, "''");
    await psqlExec(`UPDATE legal_violations SET status = 'resolved', resolved_at = NOW(), resolved_by = '${by}', resolution_notes = '${notes}' WHERE id = ${id}`);
    res.json({ success: true });
  } catch (e: any) {
    res.status(500).json({ error: e.message });
  }
});

// Get violation stats from DB
app.get('/api/violations/summary', async (req, res) => {
  try {
    const result = await psqlQueryJSON(`
      SELECT
        COUNT(*) FILTER (WHERE status = 'open') as open_count,
        COUNT(*) FILTER (WHERE status = 'resolved') as resolved_count,
        COUNT(*) FILTER (WHERE risk_level = 'HIGH') as high_risk,
        COUNT(*) FILTER (WHERE risk_level = 'MEDIUM') as medium_risk,
        COUNT(*) FILTER (WHERE reported_to_cfo = true) as reported_to_cfo,
        COUNT(*) as total,
        MAX(detected_at) as last_detected
      FROM legal_violations
    `);
    res.json(result[0] || { open_count: 0, resolved_count: 0, high_risk: 0, medium_risk: 0, reported_to_cfo: 0, total: 0 });
  } catch (e: any) {
    res.status(500).json({ error: e.message });
  }
});

// Shopify webhook for product updates (DRAFT → ACTIVE monitoring)
app.post('/api/webhook/product-update', async (req, res) => {
  try {
    console.log('\n📦 Product Update Webhook Received');

    const product = req.body;
    const productId = product.id?.toString().replace(/\D/g, '') || product.admin_graphql_api_id?.toString().replace(/\D/g, '');
    const title = product.title;
    const status = product.status;

    console.log(`   Product: ${title}`);
    console.log(`   Status: ${status}`);
    console.log(`   ID: ${productId}`);

    // Check if product is being activated (draft → active)
    if (status === 'active') {
      console.log(`\n🔍 PRODUCT ACTIVATED - Checking for existing analysis: ${title}`);

      // FIRST: Check Shopify metafields - DO NOT REANALYZE if already verified
      try {
        const metafieldsResponse = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/products/${productId}/metafields.json`, {
          headers: {
            'X-Shopify-Access-Token': SHOPIFY_TOKEN,
            'Content-Type': 'application/json'
          }
        });

        const metafields = await metafieldsResponse.json();
        const statusField = metafields.metafields?.find((m: any) => m.namespace === 'legal' && m.key === 'settlement_status');
        const analysisField = metafields.metafields?.find((m: any) => m.namespace === 'legal' && m.key === 'settlement_analysis');

        if (statusField && analysisField) {
          console.log(`   ✓ Already analyzed - Status: ${statusField.value} (NO API CALL MADE)`);

          // Use stored analysis - NO new API call
          const isViolation = statusField.value === 'VIOLATION';

          if (isViolation) {
            console.log(`\n🚨 EXISTING VIOLATION DETECTED ON ACTIVATION: ${title}`);

            const sku = product.variants?.[0]?.sku || 'Unknown';

            // Escalate to needs-attention
            await escalateViolationToNeedsAttention({
              title,
              productId,
              sku,
              reasoning: analysisField.value,
              productUrl: `https://admin.shopify.com/store/${SHOPIFY_STORE.replace('.myshopify.com', '')}/products/${productId}`
            });

            stats.violations++;
          } else {
            console.log(`   ✅ Product is compliant (from stored analysis)`);
            stats.compliant++;
          }

          stats.importsMonitored++;
          return res.status(200).json({ received: true, reanalyzed: false });
        }
      } catch (metafieldError) {
        console.log(`   ⚠️ No existing analysis found, will analyze now`);
      }

      // ONLY if no metafields exist: Analyze the product
      const imageUrl = product.image?.src || product.images?.[0]?.src;
      const sku = product.variants?.[0]?.sku || 'Unknown';

      if (imageUrl) {
        console.log(`   🔬 First-time analysis (will be saved for future)`);

        // Trigger compliance check
        setTimeout(async () => {
          try {
            const checkResponse = await fetch(`http://localhost:${PORT}/api/check-image`, {
              method: 'POST',
              headers: {
                'Content-Type': 'application/json',
                'Cookie': `${SSO_TOKEN_NAME}=${SSO_TOKEN_VALUE}`
              },
              body: JSON.stringify({
                imageUrl,
                title,
                tags: product.tags || '',
                productId,
                sku
              })
            });

            const result = await checkResponse.json();

            if (!result.compliant) {
              console.log(`\n🚨 NEW VIOLATION DETECTED ON ACTIVATION: ${title}`);

              // Escalate to needs-attention
              await escalateViolationToNeedsAttention({
                title,
                productId,
                sku,
                reasoning: result.analysis,
                productUrl: `https://admin.shopify.com/store/${SHOPIFY_STORE.replace('.myshopify.com', '')}/products/${productId}`
              });

              stats.violations++;
            } else {
              console.log(`   ✅ Product is compliant`);
              stats.compliant++;
            }

            stats.importsMonitored++;
          } catch (error) {
            console.error(`   ❌ Error checking product: ${error}`);
          }
        }, 1000);
      }
    }

    res.status(200).json({ received: true });
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).json({ error: 'Webhook processing failed' });
  }
});

// Webhook to receive import notifications
app.post('/api/webhook/import', (req, res) => {
  try {
    const { title, status, settlementCheck } = req.body;

    stats.importsMonitored++;
    stats.lastImport = {
      title,
      status: settlementCheck?.status || 'unknown',
      timestamp: new Date(),
    };

    // Log the import activity
    if (settlementCheck?.violates) {
      stats.violations++;
      stats.lastViolation = {
        title,
        id: req.body.productId || 'unknown',
        timestamp: new Date(),
      };

      activityLog.push({
        timestamp: new Date(),
        type: 'violation',
        title,
        message: `🚨 VIOLATION: ${settlementCheck.reasoning}`,
      });

      console.log(`🚨 VIOLATION DETECTED: ${title}`);

      // Escalate to needs-attention agent
      escalateViolationToNeedsAttention({
        title,
        productId: req.body.productId,
        sku: req.body.sku,
        reasoning: settlementCheck.reasoning,
        productUrl: req.body.productUrl
      }).catch(err => console.error('Failed to escalate violation:', err));
    } else if (settlementCheck?.needsReview) {
      stats.needsReview++;

      activityLog.push({
        timestamp: new Date(),
        type: 'review',
        title,
        message: `⚠️  Needs Review: ${settlementCheck.reasoning}`,
      });

      console.log(`⚠️  NEEDS REVIEW: ${title}`);
    } else {
      stats.compliant++;

      activityLog.push({
        timestamp: new Date(),
        type: 'compliant',
        title,
        message: `✅ Compliant: Settlement check passed`,
      });

      console.log(`✅ COMPLIANT: ${title}`);
    }

    // Keep only last 1000 activity entries
    if (activityLog.length > 1000) {
      activityLog.splice(0, activityLog.length - 1000);
    }

    res.json({ success: true });
  } catch (error) {
    console.error('Webhook error:', error);
    res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
});

app.get('/api/settlement-criteria', (req, res) => {
  res.json(SETTLEMENT_AGREEMENT);
});

app.post('/api/scan/catalog', async (req, res) => {
  try {
    // This would scan the entire catalog
    res.json({ success: true, scanned: 0, message: 'Full catalog scan initiated' });
  } catch (error) {
    res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
});

app.post('/api/scan/new', async (req, res) => {
  try {
    // This would scan products from last 24 hours
    res.json({ success: true, scanned: 0, message: 'New products scan initiated' });
  } catch (error) {
    res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
});

app.post('/api/scan/tagged', async (req, res) => {
  try {
    // This would scan SETTLEMENT tagged products
    res.json({ success: true, scanned: 0, message: 'Tagged products scan initiated' });
  } catch (error) {
    res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
});

// Keyword search endpoint
app.get('/api/search/keyword', async (req, res) => {
  try {
    const keyword = req.query.q as string;
    console.log(`🔍 SEARCH REQUEST RECEIVED: keyword="${keyword}"`);

    if (!keyword) {
      console.error('❌ No keyword provided');
      return res.status(400).json({ error: 'Query parameter required' });
    }

    console.log(`🔎 GraphQL search for keyword "${keyword}" across ALL products...`);

    // Use GraphQL to search across ALL products (not limited to 250)
    const graphqlQuery = `
      query SearchProducts($query: String!) {
        products(first: 250, query: $query) {
          edges {
            node {
              id
              legacyResourceId
              title
              vendor
              tags
              productType
              handle
              descriptionHtml
              status
              featuredImage {
                url
                altText
              }
              variants(first: 1) {
                edges {
                  node {
                    sku
                  }
                }
              }
            }
          }
          pageInfo {
            hasNextPage
            endCursor
          }
        }
      }
    `;

    // Build search query - search in title, tag, product_type, vendor, body
    const searchQuery = `title:*${keyword}* OR tag:*${keyword}* OR product_type:*${keyword}* OR vendor:*${keyword}* OR body:*${keyword}*`;

    let allProducts: any[] = [];
    let hasNextPage = true;
    let cursor = null;
    let pageCount = 0;

    while (hasNextPage && pageCount < 20) { // Max 20 pages = 5000 products
      pageCount++;

      const queryWithCursor = cursor
        ? graphqlQuery.replace('first: 250', `first: 250, after: "${cursor}"`)
        : graphqlQuery;

      const response = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/graphql.json`, {
        method: 'POST',
        headers: {
          'X-Shopify-Access-Token': SHOPIFY_TOKEN,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          query: queryWithCursor,
          variables: { query: searchQuery }
        })
      });

      if (!response.ok) {
        console.error(`Shopify GraphQL API error: ${response.status} ${response.statusText}`);
        return res.status(500).json({ error: `Shopify GraphQL API error: ${response.status}` });
      }

      const data: any = await response.json();

      if (data.errors) {
        console.error('GraphQL errors:', data.errors);
        return res.status(500).json({ error: 'GraphQL query error' });
      }

      const edges = data.data?.products?.edges || [];
      allProducts.push(...edges.map((e: any) => e.node));

      hasNextPage = data.data?.products?.pageInfo?.hasNextPage || false;
      cursor = data.data?.products?.pageInfo?.endCursor;

      console.log(`Page ${pageCount}: Found ${edges.length} products, Total: ${allProducts.length}`);
    }

    console.log(`✅ GraphQL search complete: Found ${allProducts.length} matching products for "${keyword}"`);

    const formattedProducts = allProducts.map((p: any) => ({
      id: p.legacyResourceId,
      title: p.title,
      vendor: p.vendor,
      tags: Array.isArray(p.tags) ? p.tags.join(', ') : p.tags || '',
      product_type: p.productType,
      sku: p.variants?.edges?.[0]?.node?.sku || null,
      image: p.featuredImage?.url || null,
      online_store_url: `https://www.designerwallcoverings.com/products/${p.handle}`,
      status: p.status?.toLowerCase() || 'draft'
    }));

    // Sort by status: ACTIVE first, then DRAFT
    formattedProducts.sort((a, b) => {
      if (a.status === 'active' && b.status !== 'active') return -1;
      if (a.status !== 'active' && b.status === 'active') return 1;
      return 0;
    });

    console.log(`📦 Sending ${formattedProducts.length} formatted products to frontend (sorted by status)`);
    res.json({ products: formattedProducts, keyword, count: formattedProducts.length });
  } catch (error) {
    console.error('Keyword search error:', error);
    res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
});

// Image compliance checker endpoint - STRICT analysis with Claude
app.post('/api/check-image', async (req, res) => {
  try {
    const { imageUrl, title, tags, productId } = req.body;

    if (!imageUrl) {
      return res.status(400).json({ error: 'Image URL is required' });
    }

    // Check cache FIRST - if product already analyzed, return cached result
    const cacheKey = productId || imageUrl;
    const cached = analysisCache.get(cacheKey);
    if (cached) {
      console.log(`✓ Cache hit for: ${title}`);
      return res.json({
        compliant: cached.compliant,
        analysis: cached.analysis,
        reason: cached.compliant ? 'No violations found' : 'Settlement violation detected',
        cached: true,
        timestamp: cached.timestamp
      });
    }

    // Check Shopify metafields - DO NOT REANALYZE if already verified
    if (productId) {
      try {
        const metafieldsResponse = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/products/${productId}/metafields.json`, {
          headers: {
            'X-Shopify-Access-Token': SHOPIFY_TOKEN,
            'Content-Type': 'application/json'
          }
        });

        const metafields = await metafieldsResponse.json();
        const verifiedField = metafields.metafields?.find((m: any) => m.namespace === 'legal' && m.key === 'settlement_verified');
        const analysisField = metafields.metafields?.find((m: any) => m.namespace === 'legal' && m.key === 'settlement_analysis');
        const statusField = metafields.metafields?.find((m: any) => m.namespace === 'legal' && m.key === 'settlement_status');

        if (verifiedField && analysisField && statusField) {
          console.log(`✓ Already analyzed (${verifiedField.value}): ${title} - ${statusField.value}`);
          const isCompliant = statusField.value === 'COMPLIANT';

          // Store in cache for faster future access
          analysisCache.set(cacheKey, {
            compliant: isCompliant,
            analysis: analysisField.value,
            timestamp: new Date(verifiedField.value).getTime()
          });

          return res.json({
            compliant: isCompliant,
            analysis: analysisField.value,
            reason: isCompliant ? 'No violations found' : 'Settlement violation detected',
            cached: false,
            fromShopify: true,
            verifiedDate: verifiedField.value
          });
        }
      } catch (metafieldError) {
        console.error(`   ⚠️ Failed to check metafields:`, metafieldError);
      }
    }

    console.log(`\n🔍 STRICT analysis: ${title}`);

    // Check title FIRST for prohibited keywords
    const titleLower = title.toLowerCase();
    const hasBanana = titleLower.includes('banana');
    const hasGrape = titleLower.includes('grape');
    const hasBird = titleLower.includes('bird');
    const hasButterfly = titleLower.includes('butterfly');

    const prompt = `First, describe what you see in this wallpaper image titled "${title}" in detail.

Then determine if it matches this settlement violation criteria:

**CRITERIA SET A (Pattern Features - need ALL 3):**
- Has repeating leaves with directional variation: YES/NO
- Has open space between elements: YES/NO
- Has 2+ colors: YES/NO

**CRITERIA SET B (Prohibited Elements - need ANY 1):**
- Shows banana FRUIT or banana PODS (NOT leaves - banana leaves are OK): YES/NO
- Shows grape fruit/clusters: YES/NO
- Shows birds: YES/NO
- Shows butterflies: YES/NO

If the first 3 are ALL YES and ANY of the last 4 is YES, it's a VIOLATION.

Please respond in this exact format:

DESCRIPTION: [Detailed description of what you see]

CRITERIA SET A:
- Repeating leaves with directional variation: YES/NO
- Open space between elements: YES/NO
- Multiple colors (2+): YES/NO [list the colors you see]

CRITERIA SET B:
- Banana FRUIT or banana PODS (NOT leaves - banana leaves are OK): YES/NO
- Grape FRUIT/clusters: YES/NO
- Birds: YES/NO
- Butterflies: YES/NO

Final answer: VIOLATION or COMPLIANT`;

    const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

    const response = await anthropic.messages.create({
      model: 'claude-3-opus-20240229',
      max_tokens: 1024,
      messages: [{
        role: 'user',
        content: [
          {
            type: 'image',
            source: {
              type: 'url',
              url: imageUrl
            }
          },
          {
            type: 'text',
            text: prompt
          }
        ]
      }]
    });

    const analysisText = response.content[0].type === 'text' ? response.content[0].text : '';
    const isViolation = analysisText.includes('VIOLATION') && !analysisText.includes('COMPLIANT');

    console.log(`   ${isViolation ? '🚨 VIOLATION' : '✅ COMPLIANT'}`);
    console.log(`   Analysis: ${analysisText.substring(0, 200)}...`);

    // Store in cache for future requests
    analysisCache.set(cacheKey, {
      compliant: !isViolation,
      analysis: analysisText,
      timestamp: Date.now()
    });

    // SAVE TO SHOPIFY METAFIELDS - Legal compliance tracking
    if (productId) {
      try {
        const verificationDate = new Date().toISOString();
        const metafieldsUpdate = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/products/${productId}/metafields.json`, {
          method: 'POST',
          headers: {
            'X-Shopify-Access-Token': SHOPIFY_TOKEN,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            metafield: {
              namespace: 'legal',
              key: 'settlement_verified',
              value: verificationDate,
              type: 'single_line_text_field'
            }
          })
        });

        const analysisUpdate = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/products/${productId}/metafields.json`, {
          method: 'POST',
          headers: {
            'X-Shopify-Access-Token': SHOPIFY_TOKEN,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            metafield: {
              namespace: 'legal',
              key: 'settlement_analysis',
              value: analysisText,
              type: 'multi_line_text_field'
            }
          })
        });

        const statusUpdate = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/products/${productId}/metafields.json`, {
          method: 'POST',
          headers: {
            'X-Shopify-Access-Token': SHOPIFY_TOKEN,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            metafield: {
              namespace: 'legal',
              key: 'settlement_status',
              value: isViolation ? 'VIOLATION' : 'COMPLIANT',
              type: 'single_line_text_field'
            }
          })
        });

        // Skip updating product body_html field - we should NOT modify product descriptions
        // Only save to metafields for tracking compliance status
        console.log(`   ✅ Saved compliance status to Shopify metafields for product ${productId}`);
      } catch (metafieldError) {
        console.error(`   ⚠️ Failed to save metafields:`, metafieldError);
      }
    }

    // Add to violations list if it's a violation
    if (isViolation && productId) {
      const violation = {
        productId: productId,
        sku: req.body.sku || 'Unknown',
        title: title,
        url: `https://${SHOPIFY_STORE}/admin/products/${productId}`,
        analysis: analysisText,
        timestamp: new Date()
      };

      // Remove old entry for this product if exists
      const existingIndex = violationsList.findIndex(v => v.productId === productId);
      if (existingIndex >= 0) {
        violationsList.splice(existingIndex, 1);
      }

      violationsList.push(violation);
      console.log(`   🚨 Added to violations list: ${title}`);

      // Persist to PostgreSQL
      saveViolationToDB({
        productId,
        sku: req.body.sku || 'Unknown',
        title,
        url: `https://${SHOPIFY_STORE}/admin/products/${productId}`,
        analysis: analysisText,
        vendor: req.body.vendor || '',
        imageUrl: imageUrl,
        riskLevel: 'HIGH'
      });

      // Escalate to needs-attention
      escalateViolationToNeedsAttention({
        title,
        productId,
        sku: req.body.sku || 'Unknown',
        reasoning: analysisText,
        productUrl: `https://${SHOPIFY_STORE}/admin/products/${productId}`
      });
    }

    res.json({
      compliant: !isViolation,
      analysis: analysisText,
      reason: isViolation ? 'Settlement violation detected' : 'No violations found',
      cached: false
    });

  } catch (error) {
    console.error('Image check error:', error);
    res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
});

// Set product to DRAFT endpoint - for legal compliance enforcement
app.post('/api/set-draft', async (req, res) => {
  try {
    const { productId } = req.body;

    if (!productId) {
      return res.status(400).json({ error: 'Product ID required' });
    }

    console.log(`⚠️  Setting product ${productId} to DRAFT (legal compliance)`);

    // Use GraphQL to update product status
    const mutation = `
      mutation productUpdate($input: ProductInput!) {
        productUpdate(input: $input) {
          product {
            id
            title
            status
          }
          userErrors {
            field
            message
          }
        }
      }
    `;

    const response = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/graphql.json`, {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': SHOPIFY_TOKEN,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        query: mutation,
        variables: {
          input: {
            id: `gid://shopify/Product/${productId}`,
            status: 'DRAFT'
          }
        }
      })
    });

    if (!response.ok) {
      throw new Error(`Shopify GraphQL API error: ${response.status}`);
    }

    const result = await response.json();

    if (result.data?.productUpdate?.userErrors?.length > 0) {
      const errors = result.data.productUpdate.userErrors.map((e: any) => e.message).join(', ');
      throw new Error(`Shopify errors: ${errors}`);
    }

    console.log(`✅ Product ${productId} set to DRAFT via GraphQL`);
    console.log(`   Title: ${result.data?.productUpdate?.product?.title}`);

    // Notify needs-attention agent to complete the task
    try {
      await fetch('http://localhost:9886/api/webhook/task/complete', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ productId })
      });
      console.log(`   ✅ Notified needs-attention to complete task for product ${productId}`);
    } catch (notifyError) {
      console.error(`   ⚠️ Failed to notify needs-attention:`, notifyError);
    }

    res.json({
      success: true,
      message: 'Product set to draft',
      product: result.data?.productUpdate?.product
    });
  } catch (error) {
    console.error('Set draft error:', error);
    res.status(500).json({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
});

// URL compliance checker endpoint
app.post('/api/check-url', async (req, res) => {
  let browser;

  try {
    const { url } = req.body;

    if (!url) {
      return res.status(400).json({ error: 'URL is required' });
    }

    console.log(`\n🔍 Checking URL: ${url}`);

    // Scrape the page with Playwright
    browser = await chromium.launch({ headless: true });
    const page = await browser.newPage();

    // Try with domcontentloaded first (faster), fallback if needed
    try {
      await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
    } catch (e) {
      console.log(`   ⚠️  domcontentloaded failed, trying load...`);
      try {
        await page.goto(url, { waitUntil: 'load', timeout: 60000 });
      } catch (e2) {
        await browser.close();
        return res.status(500).json({
          error: 'Page failed to load within timeout period. The page may be too slow or unavailable.',
        });
      }
    }

    // Wait for body to ensure content is loaded
    try {
      await page.waitForSelector('body', { timeout: 10000 });
    } catch (e) {
      await browser.close();
      return res.status(500).json({
        error: 'Page body could not be loaded.',
      });
    }

    // Extract text content
    const textContent = await page.evaluate(() => {
      return document.body.innerText;
    });

    // Get title and meta description
    const title = await page.title();
    const description = await page.evaluate(() => {
      const meta = document.querySelector('meta[name="description"]');
      return meta ? meta.getAttribute('content') : '';
    });

    await browser.close();

    console.log(`   ✅ Page scraped successfully`);
    console.log(`   📄 Title: ${title}`);

    // Analyze with Anthropic
    console.log(`   🤖 Analyzing with Claude...`);

    const prompt = `You are a legal compliance expert analyzing a product page for settlement agreement violations.

SETTLEMENT CRITERIA (MUST BE ENFORCED):

A product is PROHIBITED if it contains BOTH Part A AND Part B:

Part A - Prohibited Design (ALL three must be present):
1. Repeating patterns with directional variation amongst leaves/palm fronds
2. Open space between leaves
3. More than one ink color

Part B - Prohibited Specific Elements (ANY of these):
- Banana FRUIT or banana PODS (NOT leaves - banana leaves are OK)
- Grape fruit/clusters
- Birds
- Butterflies

Acceptable Tropical Design (at least ONE must be present):
1. Tree trunks
2. Clearly represented branches
3. Fruit or animal elements (EXCEPT prohibited ones)

VIOLATION RULE: BOTH Part A (all conditions) AND Part B (any element) must be present

---

PAGE TITLE: ${title}

PAGE DESCRIPTION: ${description}

PAGE CONTENT:
${textContent.slice(0, 5000)}

---

Analyze this product page and determine if it violates the settlement agreement.

Respond in this exact format:

STATUS: [PASS or VIOLATION]

ANALYSIS:
[Detailed explanation of your findings]`;

    const message = await anthropic.messages.create({
      model: 'claude-opus-4-8',
      max_tokens: 2000,
      messages: [
        {
          role: 'user',
          content: prompt,
        },
      ],
    });

    const responseText = message.content[0].type === 'text' ? message.content[0].text : '';

    // Parse response
    const statusMatch = responseText.match(/STATUS:\s*(PASS|VIOLATION)/i);
    const analysisMatch = responseText.match(/ANALYSIS:\s*([\s\S]*)/i);

    const status = statusMatch ? statusMatch[1].toUpperCase() : 'UNKNOWN';
    const analysis = analysisMatch ? analysisMatch[1].trim() : responseText;

    console.log(`   📊 Result: ${status}`);

    return res.json({
      status,
      analysis,
      url,
      title,
    });
  } catch (error) {
    console.error('   ❌ Error checking URL:', error);

    // Make sure browser is closed
    if (browser) {
      try {
        await browser.close();
      } catch (e) {
        // Ignore close errors
      }
    }

    return res.status(500).json({
      error: error instanceof Error ? error.message : 'Unknown error',
    });
  }
});

// API: Chat endpoint for universal header
app.post('/api/chat', async (req, res) => {

  // Memory system commands
  if (message.toLowerCase().match(/^(remember|note|preference|learning):/i)) {
    const parts = message.split(':');
    const type = parts[0].toLowerCase();
    const content = parts.slice(1).join(':').trim();
    const memType = type === 'remember' ? 'note' : type as any;
    agentMemory.add(content, memType);
    return res.json({
      response: `✅ Memory saved: "${content}"`,
      success: true,
      memoryAdded: true
    });
  }

  if (message.toLowerCase().includes('show') && message.toLowerCase().includes('memor')) {
    const summary = agentMemory.getContextSummary();
    return res.json({ response: summary, success: true });
  }

  if (message.toLowerCase().includes('search memor')) {
    const query = message.split(/for|about/i)[1]?.trim() || '';
    const results = agentMemory.search(query);
    return res.json({
      response: results.length > 0
        ? 'Found memories:\n' + results.map(m => `- ${m.content}`).join('\n')
        : 'No matching memories found.',
      success: true
    });
  }

  if (message.toLowerCase().includes('forget') || message.toLowerCase().includes('delete memor')) {
    const query = message.split(/forget|delete/i)[1]?.trim() || '';
    const results = agentMemory.search(query);
    if (results.length > 0) {
      agentMemory.delete(results[0].id);
      return res.json({ response: `✅ Forgot: "${results[0].content}"`, success: true });
    }
    return res.json({ response: 'Nothing found to forget.', success: true });
  }

  try {
    const { message } = req.body;

    const systemPrompt = `You are the Legal Team Agent AI assistant for Designer Wallcoverings. Your primary role is settlement compliance monitoring.

You help with:
- Settlement agreement compliance checking
- Product design analysis for tropical patterns
- Legal risk assessment
- Compliance violations review
- Settlement criteria interpretation

Be professional, precise, and compliance-focused. Provide clear guidance on settlement requirements.`;

    const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY || '' });

    const response = await anthropic.messages.create({
      model: 'claude-3-5-sonnet-20241022',
      max_tokens: 1024,
      system: systemPrompt,
      messages: [{ role: 'user', content: message }],
    });

    const assistantMessage = response.content[0].type === 'text' ? response.content[0].text : '';

    res.json({
      response: assistantMessage,
      success: true
    });
  } catch (error: any) {
    res.status(500).json({ error: error.message });
  }
});

// Track last check timestamp for newly active products
let lastCheckTimestamp = new Date(Date.now() - 60 * 60 * 1000); // Start 1 hour ago to catch recent activations

// Scheduled job to check for newly activated products (DRAFT → ACTIVE)
async function checkForNewlyActiveProducts() {
  try {
    const now = new Date();
    console.log(`\n🔍 [${now.toLocaleTimeString()}] Checking for newly activated products since ${lastCheckTimestamp.toLocaleTimeString()}...`);

    // GraphQL query to get products updated since last check
    const graphqlQuery = `
      query GetRecentlyUpdatedProducts {
        products(first: 100, query: "status:active updated_at:>='${lastCheckTimestamp.toISOString()}'", sortKey: UPDATED_AT, reverse: true) {
          edges {
            node {
              id
              legacyResourceId
              title
              status
              updatedAt
              tags
              featuredImage {
                url
              }
              variants(first: 1) {
                edges {
                  node {
                    sku
                  }
                }
              }
            }
          }
        }
      }
    `;

    const response = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/graphql.json`, {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': SHOPIFY_TOKEN,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query: graphqlQuery })
    });

    if (!response.ok) {
      console.error(`   ❌ GraphQL API error: ${response.status}`);
      return;
    }

    const data: any = await response.json();

    if (data.errors) {
      console.error('   ❌ GraphQL errors:', data.errors);
      return;
    }

    const products = data.data?.products?.edges || [];

    if (products.length === 0) {
      console.log(`   ✓ No newly activated products found`);
      lastCheckTimestamp = now;
      return;
    }

    console.log(`   📦 Found ${products.length} recently updated active products`);

    // Check each product for compliance
    for (const edge of products) {
      const product = edge.node;
      const productId = product.legacyResourceId;
      const title = product.title;
      const imageUrl = product.featuredImage?.url;
      const sku = product.variants?.edges?.[0]?.node?.sku || 'Unknown';

      console.log(`\n   🔬 Reviewing: ${title} (ID: ${productId})`);

      // Check if already analyzed (metafields)
      try {
        const metafieldsResponse = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/products/${productId}/metafields.json`, {
          headers: {
            'X-Shopify-Access-Token': SHOPIFY_TOKEN,
            'Content-Type': 'application/json'
          }
        });

        const metafields = await metafieldsResponse.json();
        const statusField = metafields.metafields?.find((m: any) => m.namespace === 'legal' && m.key === 'settlement_status');
        const analysisField = metafields.metafields?.find((m: any) => m.namespace === 'legal' && m.key === 'settlement_analysis');

        if (statusField && analysisField) {
          console.log(`      ✓ Already analyzed: ${statusField.value} (NO API CALL)`);

          // If violation, escalate since it was just activated
          if (statusField.value === 'VIOLATION') {
            console.log(`      🚨 VIOLATION DETECTED - Escalating to needs-attention`);

            await escalateViolationToNeedsAttention({
              title,
              productId,
              sku,
              reasoning: analysisField.value,
              productUrl: `https://admin.shopify.com/store/${SHOPIFY_STORE.replace('.myshopify.com', '')}/products/${productId}`
            });
          }
          continue;
        }
      } catch (metafieldError) {
        console.log(`      ⚠️ No existing analysis - will analyze`);
      }

      // If not analyzed and has image, analyze it
      if (imageUrl) {
        console.log(`      🔬 First-time analysis (will be saved for future)`);

        try {
          const checkResponse = await fetch(`http://localhost:${PORT}/api/check-image`, {
            method: 'POST',
            headers: {
              'Content-Type': 'application/json',
              'Cookie': `${SSO_TOKEN_NAME}=${SSO_TOKEN_VALUE}`
            },
            body: JSON.stringify({
              imageUrl,
              title,
              tags: product.tags || '',
              productId,
              sku
            })
          });

          const result = await checkResponse.json();

          if (!result.compliant) {
            console.log(`      🚨 NEW VIOLATION DETECTED - Escalating`);

            await escalateViolationToNeedsAttention({
              title,
              productId,
              sku,
              reasoning: result.analysis,
              productUrl: `https://admin.shopify.com/store/${SHOPIFY_STORE.replace('.myshopify.com', '')}/products/${productId}`
            });

            stats.violations++;
          } else {
            console.log(`      ✅ Product is compliant`);
            stats.compliant++;
          }
        } catch (error) {
          console.error(`      ❌ Error analyzing product: ${error}`);
        }
      } else {
        console.log(`      ⚠️ No image - skipping analysis`);
      }
    }

    lastCheckTimestamp = now;
    console.log(`\n   ✓ Check complete at ${now.toLocaleTimeString()}`);
  } catch (error) {
    console.error('Error checking for newly active products:', error);
  }
}

// Scheduled job to check for products set to DRAFT and complete their tasks
async function checkForDraftedProducts() {
  try {
    const now = new Date();
    console.log(`\n🔍 [${now.toLocaleTimeString()}] Checking for products set to DRAFT...`);

    // GraphQL query to get draft products that were recently updated
    const graphqlQuery = `
      query GetRecentDraftProducts {
        products(first: 50, query: "status:draft updated_at:>='${new Date(Date.now() - 60000).toISOString()}'", sortKey: UPDATED_AT, reverse: true) {
          edges {
            node {
              id
              legacyResourceId
              title
              status
              updatedAt
            }
          }
        }
      }
    `;

    const response = await fetch(`https://${SHOPIFY_STORE}/admin/api/${API_VERSION}/graphql.json`, {
      method: 'POST',
      headers: {
        'X-Shopify-Access-Token': SHOPIFY_TOKEN,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ query: graphqlQuery })
    });

    if (!response.ok) {
      console.error(`   ❌ GraphQL API error: ${response.status}`);
      return;
    }

    const data: any = await response.json();
    const products = data.data?.products?.edges || [];

    if (products.length > 0) {
      console.log(`   📦 Found ${products.length} recently drafted products`);

      for (const edge of products) {
        const product = edge.node;
        const productId = product.legacyResourceId;

        // Notify needs-attention to complete the task
        try {
          await fetch('http://localhost:9886/api/webhook/task/complete', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ productId })
          });
          console.log(`      ✅ Completed task for drafted product ${productId}`);
        } catch (error) {
          console.error(`      ⚠️ Failed to complete task for ${productId}:`, error);
        }
      }
    }
  } catch (error) {
    console.error('Error checking for drafted products:', error);
  }
}

// Start server

// Metrics endpoint for daily reporting
app.get("/api/metrics", (req: Request, res: Response) => {
  res.json({
    status: "online",
    uptime: process.uptime(),
    responseTime: 0,
    tasksCompleted: 0,
    errorsToday: 0,
    lastActivity: new Date().toISOString(),
    qnaReadiness: 100
  });
});

// Hook execution endpoint
app.post('/api/hooks/:hookName', async (req, res) => {
  const { hookName } = req.params;
  const { action } = req.body;

  try {
    const cmd = `node /root/Projects/Designer-Wallcoverings/DW-MCP/DW-Hooks/${hookName}-hook.js ${action || ''}`.trim();

    exec(cmd, { timeout: 30000 }, (error, stdout, stderr) => {
      if (error) {
        console.error('Hook execution error:', error);
        return res.status(500).json({
          success: false,
          error: stderr || error.message
        });
      }

      res.json({
        success: true,
        output: stdout
      });
    });
  } catch (err) {
    console.error('Hook error:', err);
    res.status(500).json({
      success: false,
      error: err.message
    });
  }
});

app.listen(PORT, () => {
  console.log('');
  console.log('⚖️  DW Legal Team - Settlement Compliance Monitor');
  console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
  console.log('🚨 PRIORITY #1: SETTLEMENT AGREEMENT COMPLIANCE');
  console.log('');
  console.log(`🌍 Access at: http://45.61.58.125:${PORT}`);
  console.log(`🏠 Local: http://localhost:${PORT}`);
  console.log('');
  console.log('📋 Settlement Criteria Loaded');
  console.log('✓ Part A: Prohibited Design Pattern');
  console.log('✓ Part B: Prohibited Specific Elements');
  console.log('✓ Acceptable Elements Defined');
  console.log('');
  console.log('🔍 Monitoring active...');
  console.log('');
  console.log('⏰ DRAFT→ACTIVE Monitoring: Every 15 seconds');
  console.log('   Checking for newly activated products via GraphQL polling');
  console.log('⏰ ACTIVE→DRAFT Monitoring: Every 15 seconds');
  console.log('   Auto-removing tasks when products are set to DRAFT');
  console.log('');

  // Run check every 15 seconds for newly activated products (INSTANT detection)
  setInterval(checkForNewlyActiveProducts, 15 * 1000);

  // Run check every 15 seconds for drafted products (INSTANT removal)
  setInterval(checkForDraftedProducts, 15 * 1000);

  // Run initial checks after 5 seconds
  setTimeout(checkForNewlyActiveProducts, 5000);
  setTimeout(checkForDraftedProducts, 8000);
});