/**
 * Seed Default Roles
 *
 * Populates the roles MongoDB collection with five default roles on server startup.
 * Uses $setOnInsert via bulkWrite upsert so existing roles are never overwritten,
 * preserving any manual edits made by administrators.
 *
 * Called from src/backend/src/index.ts after database connection.
 */

import { getModels } from '../models';
import type { IPermission } from '../models/Role';

// ---------------------------------------------------------------------------
// Module list (must match the MODULES array in src/frontend/src/lib/modules.ts)
// ---------------------------------------------------------------------------

const ALL_MODULES = [
  // Foundation
  'business-profile', 'founders', 'employees', 'products', 'icp-personas', 'competitors',
  // Brand
  'brand', 'brand-strategy', 'visual-identity', 'brand-manual', 'brand-assets', 'stationery', 'hr-assets',
  // Content & SEO
  'seo', 'blog-content-os', 'case-studies', 'testimonials', 'faq-bank',
  'website-planner', 'newsletter-content-os', 'social-media-os',
  // Sales
  'landing-pages', 'whatsapp-nurturing', 'sales-scripts', 'sales-collateral', 'video-content',
  'audio-content', 'books', 'intro-scripts',
  // Marketing
  'ads', 'pr', 'email-templates', 'courses', 'events', 'guerrilla-marketing',
  'interview-media-prep', 'speaking-engagements', 'moat-analysis', 'marketing-calendar',
  'marketing-channels', 'influencer', 'gmb', 'email-signature',
  // Programs
  'loyalty-programme', 'membership-plans', 'referral-programme', 'sops',
  // Operations
  'legal-documents', 'ai-processing',
  // Publishing & Funding
  'magazine-sponsorship', 'funding', 'presentations',
  // System
  'ai-chat', 'branding-settings',
] as const;

// Module groups for permission categorisation
const FOUNDATION_MODULES = [
  'business-profile', 'founders', 'employees', 'products', 'icp-personas', 'competitors',
];

const BRAND_MODULES = [
  'brand', 'brand-strategy', 'visual-identity', 'brand-manual', 'brand-assets', 'stationery', 'hr-assets',
];

const CONTENT_MODULES = [
  'seo', 'blog-content-os', 'case-studies', 'testimonials', 'faq-bank',
  'website-planner', 'newsletter-content-os', 'social-media-os',
];

const SALES_MODULES = [
  'landing-pages', 'whatsapp-nurturing', 'sales-scripts', 'sales-collateral', 'video-content',
  'audio-content', 'books', 'intro-scripts',
];

const MARKETING_MODULES = [
  'ads', 'pr', 'email-templates', 'courses', 'events', 'guerrilla-marketing',
  'interview-media-prep', 'speaking-engagements', 'moat-analysis', 'marketing-calendar',
  'marketing-channels', 'influencer', 'gmb', 'email-signature',
];

const PROGRAMS_MODULES = [
  'loyalty-programme', 'membership-plans', 'referral-programme', 'sops',
];

const OPERATIONS_MODULES = [
  'legal-documents', 'ai-processing',
];

const SYSTEM_MODULES = [
  'ai-chat', 'branding-settings',
];

// Valid actions
const ALL_ACTIONS: string[] = [
  'view', 'create', 'edit', 'delete', 'ai-generate', 'export', 'import',
  'download', 'upload', 'generate', 'manage', 'assign', 'share', 'approve', 'publish',
];

// Helper: build permissions for given modules + actions
function buildPermissions(modules: readonly string[], actions: string[]): IPermission[] {
  return modules.map((module) => ({
    module,
    actions: [...actions], // clone to avoid shared-reference issues
  }));
}

// ---------------------------------------------------------------------------
// Role definitions
// ---------------------------------------------------------------------------

const DEFAULT_ROLES = [
  // ── Super Admin ──────────────────────────────────────────────────────────
  {
    name: 'super-admin',
    displayName: 'Super Admin',
    description: 'Full unrestricted access to all modules and actions. System role that cannot be modified or deleted.',
    isDefault: false,
    isOrgDefault: false,
    isSystem: true,
    isActive: true,
    scope: 'global',
    permissions: buildPermissions(ALL_MODULES, ALL_ACTIONS),
  },
  // ── Admin ────────────────────────────────────────────────────────────────
  {
    name: 'admin',
    displayName: 'Admin',
    description: 'Full access to all modules and actions. Can be customised per organisation.',
    isDefault: false,
    isOrgDefault: false,
    isSystem: false,
    isActive: true,
    scope: 'global',
    permissions: buildPermissions(ALL_MODULES, ALL_ACTIONS),
  },
  // ── Manager ──────────────────────────────────────────────────────────────
  // Full access (view, create, edit, delete, ai-generate, export, manage) on all
  // modules EXCEPT system modules which only get view.
  {
    name: 'manager',
    displayName: 'Manager',
    description: 'Full access: can view, create, edit, delete, AI-generate, export, and manage most modules. System modules are view-only.',
    isDefault: false,
    isOrgDefault: false,
    isSystem: false,
    isActive: true,
    scope: 'global',
    permissions: [
      ...buildPermissions(
        [...FOUNDATION_MODULES, ...BRAND_MODULES, ...CONTENT_MODULES,
         ...SALES_MODULES, ...MARKETING_MODULES, ...PROGRAMS_MODULES,
         ...OPERATIONS_MODULES],
        ['view', 'create', 'edit', 'delete', 'ai-generate', 'export', 'manage'],
      ),
      ...buildPermissions(SYSTEM_MODULES, ['view']),
    ],
  },
  // ── Editor ───────────────────────────────────────────────────────────────
  // View + Edit only on content/sales/marketing modules; view-only on
  // foundation, brand, and programs modules. No create, delete, ai-generate,
  // or export.
  {
    name: 'editor',
    displayName: 'Editor',
    description: 'Can view and edit content, sales, and marketing modules. View-only on foundation, brand, and programs modules.',
    isDefault: false,
    isOrgDefault: false,
    isSystem: false,
    isActive: true,
    scope: 'global',
    permissions: [
      ...buildPermissions([...CONTENT_MODULES, ...SALES_MODULES, ...MARKETING_MODULES], ['view', 'edit']),
      ...buildPermissions([...FOUNDATION_MODULES, ...BRAND_MODULES, ...PROGRAMS_MODULES], ['view']),
    ],
  },
  // ── Viewer ───────────────────────────────────────────────────────────────
  // View-only on all modules.
  {
    name: 'viewer',
    displayName: 'Viewer',
    description: 'View-only access across all modules.',
    isDefault: true,
    isOrgDefault: false,
    isSystem: false,
    isActive: true,
    scope: 'global',
    permissions: buildPermissions(ALL_MODULES, ['view']),
  },
];

// ---------------------------------------------------------------------------
// Seed function
// ---------------------------------------------------------------------------

export async function seedRoles(): Promise<void> {
  try {
    const { Role } = getModels();

    // Migration: drop the old name_1 unique index if it exists, since we now use name_1_scope_1
    try {
      const indexes = await Role.collection.indexes();
      const hasOldNameIndex = indexes.some((idx: any) => idx.name === 'name_1');
      if (hasOldNameIndex) {
        await Role.collection.dropIndex('name_1');
        console.log('[Seed] Dropped old name_1 unique index (replaced by name_1_scope_1)');
      }
    } catch (err: any) {
      // Index may not exist, that's fine
      console.log('[Seed] Index migration note:', err.message);
    }

    // Migration: add scope field to existing roles that don't have it
    try {
      await Role.updateMany(
        { scope: { $exists: false } },
        { $set: { scope: 'global', isOrgDefault: false } }
      );
    } catch (err: any) {
      // Non-blocking
    }

    const operations = DEFAULT_ROLES.map((role) => ({
      updateOne: {
        filter: { name: role.name, scope: role.scope },
        update: {
          $setOnInsert: {
            name: role.name,
            displayName: role.displayName,
            description: role.description,
            isDefault: role.isDefault,
            isOrgDefault: role.isOrgDefault,
            isSystem: role.isSystem,
            isActive: role.isActive,
            scope: role.scope,
            permissions: role.permissions,
          },
        },
        upsert: true,
      },
    }));

    const result = await Role.bulkWrite(operations);
    const seeded = result.upsertedCount ?? 0;
    const skipped = DEFAULT_ROLES.length - seeded;

    // Update existing roles with the latest permissions list.
    // $setOnInsert only runs on creation, so existing roles may have stale
    // module lists if new modules were added to ALL_MODULES. This ensures
    // that default roles always have the complete, current permission set.
    for (const role of DEFAULT_ROLES) {
      await Role.updateOne(
        { name: role.name, scope: role.scope },
        { $set: { permissions: role.permissions } }
      );
    }

    // Reset ALL default-named roles (super-admin/admin/manager/editor/viewer)
    // across EVERY scope (global + per-organisation) to the canonical permission
    // set on every startup. This guarantees default roles reflect the latest seed
    // (e.g. Manager now has 'delete', Editor is view+edit only, newly-added
    // modules are covered) regardless of which scope a user's role lives in.
    // Custom roles (any other name, e.g. "Manageable") are never touched.
    for (const role of DEFAULT_ROLES) {
      await Role.updateMany(
        { name: role.name },
        { $set: { permissions: role.permissions as any } }
      );
    }

    console.log(`[Seed] Roles: ${seeded} created, ${skipped} already existed (updated permissions across all scopes)`);
  } catch (error) {
    console.error('[Seed] Error seeding default roles:', error);
    // Don't throw — seeding failure shouldn't crash the server
  }
}