// Check types + tester personas — parallel to Python's testersai.checks.
// Users can pass any mix of CheckType values, alias strings, tester first-names,
// Tester objects, or CustomTester objects to analyze_*.

'use strict';

const CheckType = Object.freeze({
  ACCESSIBILITY:  'accessibility',
  SECURITY:       'security',
  PRIVACY:        'privacy',
  PERFORMANCE:    'performance',
  USABILITY:      'usability',
  CONTENT:        'content',
  FORMS:          'forms',
  SEARCH:         'search',
  PUBLISHING:     'publishing',
  LANDING_PAGE:   'landing_page',
  CHECKOUT:       'checkout',
  CART:           'cart',
  PRICING:        'pricing',
  ERROR_UX:       'error_ux',
  AI_CODE:        'ai_code',
  AI_CHATBOT:     'ai_chatbot',
});

const CHECK_VALUES = new Set(Object.values(CheckType));

const ALIASES = {
  a11y: 'accessibility', ally: 'accessibility', wcag: 'accessibility',
  sec: 'security', appsec: 'security', owasp: 'security',
  perf: 'performance', web_vitals: 'performance',
  ux: 'usability',
  copy: 'content', spelling: 'content', seo: 'content',
  form: 'forms',
  landing: 'landing_page',
  ecommerce: 'checkout', payment: 'checkout',
  gdpr: 'privacy', ccpa: 'privacy', pii: 'privacy',
  chatbot: 'ai_chatbot',
  vibe_coding: 'ai_code',
  errors: 'error_ux',
};

// 21 built-in personas — mirrors https://testers.ai.
const TESTERS = Object.freeze([
  { key: 'sharon',    name: 'Sharon',    role: 'Security Tester',          focus: 'OWASP Top 10',       checks: ['security'] },
  { key: 'marcus',    name: 'Marcus',    role: 'OWASP Security',           focus: 'AppSec',             checks: ['security'] },
  { key: 'mia',       name: 'Mia',       role: 'Usability Expert',         focus: 'UX Heuristics',      checks: ['usability'] },
  { key: 'alejandro', name: 'Alejandro', role: 'Accessibility Specialist', focus: 'WCAG 2.2 AA',        checks: ['accessibility'] },
  { key: 'hiroshi',   name: 'Hiroshi',   role: 'WCAG Compliance',          focus: 'WCAG AAA',           checks: ['accessibility'] },
  { key: 'pete',      name: 'Pete',      role: 'Privacy Analyst',          focus: 'GDPR / CCPA',        checks: ['privacy'] },
  { key: 'zanele',    name: 'Zanele',    role: 'GDPR Specialist',          focus: 'EU Privacy',         checks: ['privacy'] },
  { key: 'rajesh',    name: 'Rajesh',    role: 'Cookie Consent Tester',    focus: 'Cookie Law',         checks: ['privacy'] },
  { key: 'sundar',    name: 'Sundar',    role: 'Legal Policy Reviewer',    focus: 'Legal Compliance',   checks: ['privacy'] },
  { key: 'jason',     name: 'Jason',     role: 'GenAI Code Reviewer',      focus: 'Vibe Coding',        checks: ['ai_code'] },
  { key: 'diego',     name: 'Diego',     role: 'AI Chatbot Tester',        focus: 'Conversational AI',  checks: ['ai_chatbot'] },
  { key: 'tariq',     name: 'Tariq',     role: 'Performance Engineer',     focus: 'Core Vitals',        checks: ['performance'] },
  { key: 'fatima',    name: 'Fatima',    role: 'Error Message Analyst',    focus: 'Error UX',           checks: ['error_ux'] },
  { key: 'sophia',    name: 'Sophia',    role: 'Content Quality Auditor',  focus: 'Content QA',         checks: ['content'] },
  { key: 'richard',   name: 'Richard',   role: 'Forms Specialist',         focus: 'Form UX',            checks: ['forms'] },
  { key: 'mei',       name: 'Mei',       role: 'Search Box Tester',        focus: 'Search UX',          checks: ['search'] },
  { key: 'zara',      name: 'Zara',      role: 'News & Content',           focus: 'Publishing QA',      checks: ['publishing'] },
  { key: 'yuki',      name: 'Yuki',      role: 'Landing Page Analyst',     focus: 'Conversion QA',      checks: ['landing_page'] },
  { key: 'hassan',    name: 'Hassan',    role: 'Checkout Tester',          focus: 'E-commerce',         checks: ['checkout'] },
  { key: 'priya',     name: 'Priya',     role: 'Shopping Cart Tester',     focus: 'Cart Flows',         checks: ['cart'] },
  { key: 'mateo',     name: 'Mateo',     role: 'Pricing Page Tester',      focus: 'SaaS Pricing',       checks: ['pricing'] },
]);

const TESTERS_BY_KEY = Object.fromEntries(TESTERS.map((t) => [t.key, t]));

/**
 * Create a custom tester definition that gets evaluated alongside the built-ins.
 * Pass instances of CustomTester inside `testers=[...]` on any analyze_* call.
 */
function customTester({ name, role, instructions, focus = 'custom', tags = [], checks = [] }) {
  return {
    __testersai_custom: true,
    name, role, instructions, focus,
    tags: Array.isArray(tags) ? [...tags] : [],
    checks: Array.isArray(checks) ? [...checks] : [],
  };
}

function _normalize(tok) {
  if (tok && typeof tok === 'object' && tok.__testersai_custom) {
    // CustomTester — re-shape for wire
    return ['custom', {
      custom: true,
      name: tok.name, role: tok.role, focus: tok.focus,
      instructions: tok.instructions,
      tags: [...(tok.tags || [])],
      checks: [...(tok.checks || [])],
    }];
  }
  if (tok && typeof tok === 'object' && tok.key && tok.checks && tok.role) {
    // Tester object from TESTERS
    return ['tester', tok.key];
  }
  if (typeof tok === 'string') {
    const k = tok.trim().toLowerCase().replace(/[- ]/g, '_');
    if (CHECK_VALUES.has(k)) return ['check', k];
    if (ALIASES[k])          return ['check', ALIASES[k]];
    if (TESTERS_BY_KEY[k])   return ['tester', k];
  }
  return ['unknown', tok];
}

function resolve(tokens) {
  const checks = [], testers = [], custom_testers = [], unknown = [];
  const seenC = new Set(), seenT = new Set();
  for (const tok of tokens || []) {
    const [cat, val] = _normalize(tok);
    if (cat === 'check')        { if (!seenC.has(val)) { seenC.add(val); checks.push(val); } }
    else if (cat === 'tester')  { if (!seenT.has(val)) { seenT.add(val); testers.push(val); } }
    else if (cat === 'custom')  custom_testers.push(val);
    else                        unknown.push(val);
  }
  return { checks, testers, custom_testers, unknown };
}

module.exports = { CheckType, TESTERS, TESTERS_BY_KEY, customTester, resolve };
