#!/usr/bin/env node
/**
 * Replace old hand-written CSS class names with Tailwind v4 equivalents.
 * SAFE version: only replaces inside class="..." attribute values.
 *
 * Run: node scripts/cleanup-css.mjs
 */

import { readFileSync, writeFileSync } from 'fs';
import { globSync } from 'glob';

// Order matters: most-specific (multi-word) patterns first.
// Each entry: [old-class-string, new-tailwind-classes]
const REPLACEMENTS = [
  // ── Page structure ──────────────────────────────────────────────
  ['page-hero-card page-actions', 'mb-6 flex items-start justify-between gap-4'],
  ['page-actions-right', 'flex items-center gap-2'],
  ['page-actions', 'mb-6 flex items-start justify-between gap-4'],
  ['page-title-block', 'flex flex-col gap-1'],
  ['page-title', 'text-2xl font-bold text-gray-900'],
  ['page-subtitle', 'mt-1 text-sm text-gray-500'],

  // ── Card ────────────────────────────────────────────────────────
  ['card', 'rounded-xl border border-gray-200 bg-white shadow-sm'],

  // ── Buttons (specific before generic) ───────────────────────────
  ['btn navy', 'inline-flex items-center rounded-lg bg-[#fd6216] px-4 py-2 text-sm font-semibold text-white hover:bg-orange-600 transition-colors'],
  ['btn primary', 'inline-flex items-center rounded-lg bg-[#fd6216] px-4 py-2 text-sm font-semibold text-white hover:bg-orange-600 transition-colors'],
  ['btn danger', 'inline-flex items-center rounded-lg border border-red-200 bg-red-50 px-4 py-2 text-sm font-medium text-red-600 hover:bg-red-100 transition-colors'],
  ['btn sm', 'inline-flex items-center rounded-md border border-gray-200 bg-white px-3 py-1.5 text-xs font-medium text-gray-700 hover:bg-gray-50 transition-colors'],
  ['btn', 'inline-flex items-center rounded-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors'],

  // ── Table ────────────────────────────────────────────────────────
  ['table-wrap', 'overflow-x-auto'],
  ['list-table', 'w-full text-sm'],
  ['perm-table', 'w-full text-sm'],
  ['table-actions', 'flex items-center justify-end gap-1'],
  ['align-right', 'text-right'],
  ['row-selected', 'bg-orange-50'],

  // ── Icon action buttons ──────────────────────────────────────────
  ['action-icon-btn danger', 'rounded p-1.5 text-red-500 hover:bg-red-50 hover:text-red-700 text-sm'],
  ['action-icon-btn', 'rounded p-1.5 text-gray-500 hover:bg-gray-100 hover:text-gray-700 text-sm'],

  // ── Status chips (specific before generic) ───────────────────────
  ['status-chip active', 'inline-flex items-center rounded-full bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-700'],
  ['status-chip pending', 'inline-flex items-center rounded-full bg-amber-100 px-2.5 py-0.5 text-xs font-medium text-amber-700'],
  ['status-chip inactive', 'inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-500'],
  ['status-chip', 'inline-flex items-center rounded-full bg-gray-100 px-2.5 py-0.5 text-xs font-medium text-gray-600'],

  // ── Error / notice ───────────────────────────────────────────────
  ['error-box', 'mb-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700'],

  // ── Form sections ────────────────────────────────────────────────
  ['role-form-section', 'mb-6 rounded-xl border border-gray-200 bg-white p-6 shadow-sm'],
  ['field-grid-2', 'mt-4 grid grid-cols-1 gap-4 sm:grid-cols-2'],
  ['module-picker', 'mt-3 flex flex-wrap gap-2'],
  ['module-chip selected', 'flex cursor-pointer items-center gap-1.5 rounded-full border border-orange-300 bg-orange-50 px-3 py-1.5 text-xs font-medium text-orange-700'],
  ['module-chip', 'flex cursor-pointer items-center gap-1.5 rounded-full border border-gray-200 bg-white px-3 py-1.5 text-xs font-medium text-gray-600 hover:border-gray-300'],

  // ── Legacy tab nav (now handled by AdminShell) ────────────────────
  ['admin-link-tabs', 'hidden'],
  ['admin-link-tab active', 'hidden'],
  ['admin-link-tab', 'hidden'],
];

/**
 * Replace old CSS class names only inside JSX class attribute values.
 * Handles:
 *   class="foo bar baz"
 *   class={'foo bar baz'}
 *   class={`foo bar baz`}
 *   class={condition ? 'foo' : 'bar'}
 *
 * We do this by extracting the string portion of class attributes and
 * replacing only within those extracted portions.
 */
function replaceInClassAttributes(src) {
  let changed = false;

  // Process class="..." and class='...' (static strings)
  src = src.replace(/class=["']([^"']*)["']/g, (match, classes) => {
    let replaced = classes;
    for (const [from, to] of REPLACEMENTS) {
      // Replace whole-word occurrences within the class string
      // Use word boundaries to avoid partial matches
      const re = new RegExp(`(?<![\\w-])${escapeRe(from)}(?![\\w-])`, 'g');
      replaced = replaced.replace(re, to);
    }
    if (replaced !== classes) changed = true;
    const quote = match[6] === '"' ? '"' : "'"; // char after `class=`
    return `class=${quote}${replaced}${quote}`;
  });

  // Process class={`...`} (template literals with static content)
  src = src.replace(/class=\{`([^`]*)`\}/g, (match, classes) => {
    let replaced = classes;
    for (const [from, to] of REPLACEMENTS) {
      const re = new RegExp(`(?<![\\w-])${escapeRe(from)}(?![\\w-])`, 'g');
      replaced = replaced.replace(re, to);
    }
    if (replaced !== classes) changed = true;
    return `class={\`${replaced}\`}`;
  });

  // Process class={'...'} and class={"..."} (single-expression strings)
  src = src.replace(/class=\{(['"])([^'"]*)\1\}/g, (match, q, classes) => {
    let replaced = classes;
    for (const [from, to] of REPLACEMENTS) {
      const re = new RegExp(`(?<![\\w-])${escapeRe(from)}(?![\\w-])`, 'g');
      replaced = replaced.replace(re, to);
    }
    if (replaced !== classes) changed = true;
    return `class={${q}${replaced}${q}}`;
  });

  // Process ternary class values: class={cond ? 'foo' : 'bar'}
  // Match string literals inside class={...} expressions
  src = src.replace(/class=\{[^}]+\}/g, (match) => {
    // Replace inside single/double-quoted string literals within the expression
    const replaced = match.replace(/'([^']*)'/g, (m, inner) => {
      let r = inner;
      for (const [from, to] of REPLACEMENTS) {
        const re = new RegExp(`(?<![\\w-])${escapeRe(from)}(?![\\w-])`, 'g');
        r = r.replace(re, to);
      }
      if (r !== inner) changed = true;
      return `'${r}'`;
    }).replace(/"([^"]*)"/g, (m, inner) => {
      // skip JSX attributes within the expression (avoid double replacement)
      let r = inner;
      for (const [from, to] of REPLACEMENTS) {
        const re = new RegExp(`(?<![\\w-])${escapeRe(from)}(?![\\w-])`, 'g');
        r = r.replace(re, to);
      }
      if (r !== inner) changed = true;
      return `"${r}"`;
    });
    return replaced;
  });

  return { src, changed };
}

function escapeRe(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

const files = globSync('src/routes/admin/**/*.tsx', {
  cwd: '/Users/ashwin/workspace/nxtgauge-admin-solid',
  absolute: true,
});

let totalChanged = 0;

for (const file of files) {
  const original = readFileSync(file, 'utf8');
  const { src, changed } = replaceInClassAttributes(original);

  if (changed) {
    writeFileSync(file, src, 'utf8');
    totalChanged++;
    console.log(`  updated: ${file.replace('/Users/ashwin/workspace/nxtgauge-admin-solid/', '')}`);
  }
}

console.log(`\nDone. Updated ${totalChanged} / ${files.length} files.`);
