import { logger } from '../logger.js';
import type { ReferenceResolver } from './classes.reference-resolver.js';
import type { IRouteSecurity } from '../../ts_interfaces/data/route-management.js';

export interface ISeedData {
  profiles?: Array<{
    name: string;
    description?: string;
    security: IRouteSecurity;
    extendsProfiles?: string[];
  }>;
  targets?: Array<{
    name: string;
    description?: string;
    host: string | string[];
    port: number;
  }>;
}

export class DbSeeder {
  constructor(private referenceResolver: ReferenceResolver) {}

  /**
   * Check if DB is empty and seed if configured.
   * Called once during ConfigManagers service startup, after initialize().
   */
  public async seedIfEmpty(
    seedOnEmpty?: boolean,
    seedData?: ISeedData,
  ): Promise<void> {
    if (!seedOnEmpty) return;

    const existingProfiles = this.referenceResolver.listProfiles();
    const existingTargets = this.referenceResolver.listTargets();

    if (existingProfiles.length > 0 || existingTargets.length > 0) {
      logger.log('info', 'DB already contains profiles/targets, skipping seed');
      return;
    }

    logger.log('info', 'Seeding database with initial profiles and targets...');

    const profilesToSeed: NonNullable<ISeedData['profiles']> = seedData?.profiles ?? DEFAULT_PROFILES;
    const targetsToSeed: NonNullable<ISeedData['targets']> = seedData?.targets ?? DEFAULT_TARGETS;

    for (const p of profilesToSeed) {
      await this.referenceResolver.createProfile({
        name: p.name,
        description: p.description,
        security: p.security,
        extendsProfiles: p.extendsProfiles,
        createdBy: 'system-seed',
      });
    }

    for (const t of targetsToSeed) {
      await this.referenceResolver.createTarget({
        name: t.name,
        description: t.description,
        host: t.host,
        port: t.port,
        createdBy: 'system-seed',
      });
    }

    logger.log('info', `Seeded ${profilesToSeed.length} profile(s) and ${targetsToSeed.length} target(s)`);
  }
}

const DEFAULT_PROFILES: Array<NonNullable<ISeedData['profiles']>[number]> = [
  {
    name: 'TRUSTED NETWORKS',
    description: 'Trusted office, VPN, localhost, and private-network sources with high connection allowance',
    security: {
      ipAllowList: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.1', '::1'],
      maxConnections: 5000,
    },
  },
  {
    name: 'AI CRAWLERS',
    description: 'Add verified crawler CIDRs before assigning this profile in a source policy',
    security: {
      ipAllowList: [],
      rateLimit: {
        enabled: true,
        maxRequests: 30,
        window: 60,
        keyBy: 'ip',
      },
    },
  },
  {
    name: 'PUBLIC',
    description: 'Public fallback source profile with per-IP request limiting',
    security: {
      ipAllowList: ['*'],
      rateLimit: {
        enabled: true,
        maxRequests: 120,
        window: 60,
        keyBy: 'ip',
      },
    },
  },
  {
    name: 'STANDARD',
    description: 'Standard internal access with common private subnets',
    security: {
      ipAllowList: ['192.168.0.0/16', '10.0.0.0/8', '127.0.0.1', '::1'],
      maxConnections: 1000,
    },
  },
];

const DEFAULT_TARGETS: Array<NonNullable<ISeedData['targets']>[number]> = [
  {
    name: 'LOCALHOST',
    description: 'Local machine on port 443',
    host: '127.0.0.1',
    port: 443,
  },
];
