﻿import { Module, OnModuleInit } from '@nestjs/common';
import * as Handlebars from 'handlebars';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule, getDataSourceToken } from '@nestjs/typeorm';
// import { ServeStaticModule } from '@nestjs/serve-static';
import { join } from 'path';
import { APP_GUARD } from '@nestjs/core';
import { AppController } from './app.controller';
import { AppService } from './app.service';

// Guards
import { PermissionGuard } from './common/guards/permission.guard';
import { JwtAuthGuard } from './auth/guards/jwt-auth.guard';

// Services
import { DatabaseKeepAliveService } from './common/services/database-keep-alive.service';

// Entities
import { User } from './user/entities/user.entity';
import { Role } from './role/entities/role.entity';
import { Permission } from './permission/entities/permission.entity';
import { ModuleEntity } from './modules/entities/module.entity';
import { UserPermission } from './user-permissions/entities/user-permission.entity';
import { UserPermissionCondition } from './user-permission-conditions/entities/user-permission-condition.entity';
import { UserRole } from './user-roles/entities/user-role.entity';
import { PushSubscription } from './notifications/entities/push-subscription.entity';
import { PostEntity } from './post/post.entity';
import { ClientDataEntity } from './clients/client-data.entity';
import { NewsurveSurvesEntity } from './clients/newsurve-surves.entity';
// import { Contact } from './contact/entities/contact.entities';
import { Standard } from './standards/entities/standard.entity';
import { Country } from './countries/entities/country.entity';
// import { CompaniesModule } from './companies/companies.module';
import { Company } from './companies/entities/company.entity';
import { CompanyBranch } from './companies/entities/company-branch.entity';
import { CompanyClientLink } from './companies/entities/company-client-link.entity';
import { CompanyChangeLog } from './companies/entities/company-change-log.entity';

import { CompanySequence } from './companies/entities/company-sequence.entity';
import { AuditType } from './audit-types/entities/audit-type.entity';
import { CompanyAudit } from './company-audits/entities/company-audit.entity';
import { CompanyAuditStage } from './company-audit-stages/entities/company-audit-stage.entity';
// import { NetworkFile } from './network-files/entities/network-file.entity';
import { NewCertificate } from './certificates/entities/new-certificate.entity';
import { CertificateVersionHistory } from './certificates/entities/certificate_version_history';
import { Certificate } from './excel/certificate.entity';
import { Codebook } from './excel/codebook.entity';
import { Template } from './template/entities/template.entity';
import { TemplateContent } from './template_contents/entities/template_content.entity';
import { Job } from './jobs/entities/job.entity';
import { IsoCertificate } from './iso-certificates/entities/iso-certificate.entity';

// Modules
import { RolesModule } from './roles/roles.module';
import { AuthModule } from './auth/auth.module';
import { UserModule } from './user/user.module';
import { RoleModule } from './role/role.module';
import { PermissionModule } from './permission/permission.module';
import { ModulesModule } from './modules/modules.module';
import { RolePermissionsModule } from './role-permissions/role-permissions.module';
import { UserRolesModule } from './user-roles/user-roles.module';
import { UserPermissionsModule } from './user-permissions/user-permissions.module';
import { UserPermissionConditionsModule } from './user-permission-conditions/user-permission-conditions.module';
import { EmailSettingsModule } from './email-settings/email-settings.module';
import { MailsModule } from './mails/mails.module';
import { PostModule } from './post/post.module';
import { ClientsModule } from './clients/clients.module';
// import { ContactModule } from './contact/contact.module';
// import { NetworkFilesModule } from './network-files/network-files.module';
import { CompaniesModule } from './companies/companies.module';
import { StandardsModule } from './standards/standards.module';
import { CountriesModule } from './countries/countries.module';
import { CompanyAuditsModule } from './company-audits/company-audits.module';
import { CompanyAuditStagesModule } from './company-audit-stages/company-audit-stages.module';
import { AuditTypesModule } from './audit-types/audit-types.module';
import { ExcelModule } from './excel/excel.module';
import { PdfModule } from './pdf/pdf.module';
import { JobsModule } from './jobs/jobs.module';
import { TemplateModule } from './template/template.module';
import { TemplateContentsModule } from './template_contents/template_contents.module';
import { CertificatesModule } from './certificates/certificates.module';
import { IsoCertificatesModule } from './iso-certificates/iso-certificates.module';
import { InquiriesModule } from './inquiries/inquiries.module';
import { Inquiry } from './inquiries/entities/inquiry.entity';
import { InquiryNotificationsModule } from './inquiry-notifications/inquiry-notifications.module';
import { InquiryNotificationEntity } from './inquiry-notifications/entities/inquiry-notification.entity';
import { ChatModule } from './chat/chat.module';
import { ChatRoom } from './chat/entities/chat-room.entity';
import { ChatRoomMember } from './chat/entities/chat-room-member.entity';
import { ChatMessage } from './chat/entities/chat-message.entity';
import { AuditSchedulesModule } from './audit-schedules/audit-schedules.module';
import { AuditSchedule } from './audit-schedules/entities/audit-schedule.entity';
import { AuditScheduleRow } from './audit-schedules/entities/audit-schedule-row.entity';
import { AuditCodeSequence } from './audit-schedules/entities/audit-code-sequence.entity';
import { AuditStatusHistory } from './audit-schedules/entities/audit-status-history.entity';
import { AuditRequest } from './audit-requests/entities/audit-request.entity';
import { AuditRequestsModule } from './audit-requests/audit-requests.module';
import { MyScheduleMasterModule } from './my-schedule-master/my-schedule-master.module';   // ðŸ†•
import { NotificationsModule } from './notifications/notifications.module';
import { MeetingModule } from './meeting/meeting.module';
import { PreviousNcModule } from './previous-nc/previous-nc.module';
import { PreviousNcEntity } from './previous-nc/entities/previous-nc.entity';
import { PreviousNcrEntryEntity } from './previous-nc/entities/previous-ncr-entry.entity';
import { PreviousNcRemarkEntity } from './previous-nc/entities/previous-nc-remark.entity';
import { PreviousNcFinalClosureEntity } from './previous-nc/entities/previous-nc-final-closure.entity';
import { PreviousNcClientEntity } from './previous-nc/entities/previous-nc-client.entity';
import { PreviousNcSurveEntity } from './previous-nc/entities/previous-nc-surve.entity';
import { PreviousNcStandardEntity } from './previous-nc/entities/previous-nc-standard.entity';
import { PreviousNcUserEntity } from './previous-nc/entities/previous-nc-user.entity';
import { AuditReportModule } from './audit-report/audit-report.module';
import { ReportModule } from './report/report.module';
import { AgingAnalysisModule } from './aging-analysis/aging-analysis.module'; // â† add
import { ExpoPushToken } from './notifications/entities/expo-push-token.entity';
import { LeadModule } from './lead/lead.module';
import { ClientStandardEntity } from './clients/client-standard.entity';
import { ClientPortalModule } from './client-portal/client-portal.module';  // ✅ Add this
import { TrainingCertificatesModule } from './training-certificates/training-certificates.module';
import { ChecklistsModule } from './checklists-module/checklists.module';
import { DocumentsModule } from './documents/documents.module';


const MYSQL_KEEP_ALIVE_OPTIONS = {
  connectionLimit: 10, // max simultaneous connections
  waitForConnections: true, // queue instead of failing when pool is full
  queueLimit: 0, // unlimited queue

  enableKeepAlive: true, // send TCP keep-alive packets
  keepAliveInitialDelay: 10000, // start after 10s idle

  // â”€â”€ Timeouts â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
  connectTimeout: 30000, // 30s to establish a new connection
  // Note: acquireTimeout is NOT a valid mysql2 option â€” removed

  // â”€â”€ Idle management â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
  maxIdle: 10, // max idle connections to keep
  idleTimeout: 60000, // close idle connections after 60s

  // â”€â”€ Date handling (safer across network issues) â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
  dateStrings: false,
  charset: 'utf8mb4_unicode_ci',
};

// â”€â”€ TypeORM retry settings (applied to ALL connections) â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€
const TYPEORM_RETRY_OPTIONS = {
  retryAttempts: 10, // try 10 times on failure
  retryDelay: 3000, // 3s between retries
  autoLoadEntities: false, // we declare entities explicitly
  // keepConnectionAlive: true,        // TypeORM-level keep-alive
  // Reconnect on errors
  extra: MYSQL_KEEP_ALIVE_OPTIONS,
};

@Module({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),

    // ServeStaticModule.forRoot({
    //   rootPath: join(__dirname, '..', 'frontend'),
    //   exclude: ['/api/(.*)', '/api/pdf/certificate/(.*)'],
    // }),
    // ServeStaticModule.forRoot({
    //   rootPath: join(__dirname, '..', 'certificates'),
    //   serveRoot: '/api/pdf/certificate',
    // }),

    
    TypeOrmModule.forRoot({
      name: 'scheme_dbs',
      type: 'mysql',
      host: process.env.DB_HOST,
      port: Number(process.env.DB_PORT),
      username: process.env.DB_USERNAME,
      password: process.env.DB_PASSWORD,
      database: process.env.DB_DATABASE,
      autoLoadEntities: true,
      entities: [
        User,
        Role,
        Permission,
        ModuleEntity,
        UserPermission,
        UserPermissionCondition,
        UserRole,
        Standard,
        Country,
        Company,
        CompanyBranch,
        CompanyClientLink,
        CompanyChangeLog,
        CompanySequence,
        AuditType,
        CompanyAudit,
        CompanyAuditStage,
        PushSubscription,
        Inquiry,
        InquiryNotificationEntity,
        ChatRoom,
        ChatRoomMember,
        ChatMessage,
        NewCertificate,
        ClientPortalModule,
        CertificateVersionHistory,
        Certificate,
        AuditSchedule,
        AuditScheduleRow,
        AuditCodeSequence,
        AuditStatusHistory,
        AuditRequest,
        AuditReportModule,
        LeadModule,

      ],
      synchronize: false,
      // âœ… ADDED: keep-alive + auto-reconnect on WiFi switch
      extra: MYSQL_KEEP_ALIVE_OPTIONS,
      retryAttempts: 10,
      retryDelay: 3000,
      // keepConnectionAlive: true,
    }),

    // â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
    // WordPress DB
    // â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
    TypeOrmModule.forRoot({
      name: 'wordpressDataSource',
      type: 'mysql',
      host: process.env.DB_WORDPRESS_HOST,
      port: Number(process.env.DB_WORDPRESS_PORT),
      username: process.env.DB_WORDPRESS_USERNAME,
      password: process.env.DB_WORDPRESS_PASSWORD,
      database: process.env.DB_WORDPRESS_DATABASE,
      entities: [PostEntity],
      synchronize: false,
      extra: MYSQL_KEEP_ALIVE_OPTIONS,
      retryAttempts: 10,
      retryDelay: 3000,
      // keepConnectionAlive: true,
    }),

    // â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
    // QRS DB
    // â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
    TypeOrmModule.forRoot({
      name: 'qrs',
      type: 'mysql',
      host: process.env.DB_QRS_HOST,
      port: Number(process.env.DB_QRS_PORT),
      username: process.env.DB_QRS_USERNAME,
      password: process.env.DB_QRS_PASSWORD,
      database: process.env.DB_QRS_DATABASE,
      entities: [
        ClientDataEntity,
        NewsurveSurvesEntity,
        ClientStandardEntity,
        PreviousNcEntity,
        PreviousNcrEntryEntity,
        PreviousNcRemarkEntity,
        PreviousNcFinalClosureEntity,
        PreviousNcClientEntity,
        PreviousNcSurveEntity,
        PreviousNcStandardEntity,
        PreviousNcUserEntity,
      ],
      synchronize: false,
      extra: MYSQL_KEEP_ALIVE_OPTIONS,
      retryAttempts: 10,
      retryDelay: 3000,
      // keepConnectionAlive: true,
    }),

    // â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
    // TQS DB
    // â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
    TypeOrmModule.forRoot({
      name: 'tqs',
      type: 'mysql',
      host: process.env.DB_TQS_HOST,
      port: Number(process.env.DB_TQS_PORT),
      username: process.env.DB_TQS_USERNAME,
      password: process.env.DB_TQS_PASSWORD,
      database: process.env.DB_TQS_DATABASE,
      entities: [
        ClientDataEntity,
        NewsurveSurvesEntity,
        ClientStandardEntity,
        PreviousNcEntity,
        PreviousNcrEntryEntity,
        PreviousNcRemarkEntity,
        PreviousNcFinalClosureEntity,
        PreviousNcClientEntity,
        PreviousNcSurveEntity,
        PreviousNcStandardEntity,
        PreviousNcUserEntity,
      ],
      synchronize: false,
      extra: MYSQL_KEEP_ALIVE_OPTIONS,
      retryAttempts: 10,
      retryDelay: 3000,
      // keepConnectionAlive: true,
    }),

    
    TypeOrmModule.forRoot({
      name: 'quality_db',
      type: 'mysql',
      host: process.env.DB_QUALITY_HOST,
      port: Number(process.env.DB_QUALITY_PORT),
      username: process.env.DB_QUALITY_USERNAME,
      password: process.env.DB_QUALITY_PASSWORD,
      database: process.env.DB_QUALITY_DATABASE,
      entities: [],
      synchronize: false,
      extra: MYSQL_KEEP_ALIVE_OPTIONS,
      retryAttempts: 10,
      retryDelay: 3000,
      // keepConnectionAlive: true,
    }),

   
    TypeOrmModule.forRoot({
      name: 'certification_db',
      type: 'mysql',
      host: process.env.DB_CERT_HOST,
      port: Number(process.env.DB_CERT_PORT),
      username: process.env.DB_CERT_USERNAME,
      password: process.env.DB_CERT_PASSWORD,
      database: process.env.DB_CERT_DATABASE,
      entities: [
        User,
        Role,
        Permission,
        Standard,
        Country,
        Company,
        CompanyBranch,
        CompanyClientLink,
        CompanyChangeLog,
        CompanySequence,
        AuditType,
        CompanyAudit,
        CompanyAuditStage,
        // NetworkFile,
        ModuleEntity,
        NewCertificate,
        CertificateVersionHistory,
        Certificate,
        Codebook,
        Template,
        TemplateContent,
        Job,
        IsoCertificate,
        Inquiry,
        InquiryNotificationEntity,
        AuditRequest,
        AuditSchedule,           // ✅ ADD
        AuditScheduleRow,        // ✅ ADD
        AuditStatusHistory,      // ✅ ADD
        AuditCodeSequence,       // ✅ ADD

      ],
      synchronize: false,
      extra: MYSQL_KEEP_ALIVE_OPTIONS,
      retryAttempts: 10,
      retryDelay: 3000,
      // keepConnectionAlive: true,
    }),

    // -------------------------------
    // All Modules
    // -------------------------------
    RolesModule,
    AuthModule,
    UserModule,
    RoleModule,
    PermissionModule,
    UserPermissionsModule,
    RolePermissionsModule,
    ModulesModule,
    UserRolesModule,
    UserPermissionConditionsModule,
    EmailSettingsModule,
    MailsModule,
    PostModule,
    ClientsModule,
    ClientPortalModule,
    // ContactModule,
    // NetworkFilesModule,
    CompaniesModule,
    StandardsModule,
    CountriesModule,
    CompanyAuditsModule,
    CompanyAuditStagesModule,
    AuditTypesModule,
    ExcelModule,
    PdfModule,
    JobsModule,
    TemplateModule,
    TemplateContentsModule,
    CertificatesModule,
    ClientPortalModule,
    TrainingCertificatesModule, 
    ChecklistsModule,
    DocumentsModule,
    IsoCertificatesModule,
    InquiriesModule,
    InquiryNotificationsModule,
    NotificationsModule, // â† ADD THIS LINE
    MeetingModule,
    ChatModule,
    AuditSchedulesModule,
    AuditRequestsModule,
    MyScheduleMasterModule,
    PreviousNcModule,
    AuditReportModule,
    ReportModule,
    AgingAnalysisModule,
    LeadModule,
  ],
  providers: [
    AppService,
    // Guards (order matters)
    {
      provide: APP_GUARD,
      useClass: JwtAuthGuard, // 1st: Check token
    },
    {
      provide: APP_GUARD,
      useClass: PermissionGuard,
    },
    
    {
      provide: DatabaseKeepAliveService,
      useFactory: (schemeDs, wpDs, qrsDs, tqsDs, qualityDs, certDs) =>
        new DatabaseKeepAliveService([
          schemeDs, // âœ… ADDED â€” this was missing!
          wpDs,
          qrsDs,
          tqsDs,
          qualityDs,
          certDs,
        ]),
      inject: [
        getDataSourceToken('scheme_dbs'), // âœ… ADDED
        getDataSourceToken('wordpressDataSource'),
        getDataSourceToken('qrs'),
        getDataSourceToken('tqs'),
        getDataSourceToken('quality_db'),
        getDataSourceToken('certification_db'),
      ],
    },
  ],
})
export class AppModule implements OnModuleInit {
  onModuleInit() {
    Handlebars.registerHelper(
      'smartScope',
      function (
        scope: string,
        templateType: 'CERTIFICATE' | 'DOCUMENT' = 'DOCUMENT',
      ) {
        if (!scope) return '';

        const trimmed = scope.trim();
        const hasArrows = trimmed.includes('âž¤');

        /* =====================================================
           CERTIFICATE â†’ USER DECIDES (NO AUTO FORMATTING)
        ====================================================== */
        if (templateType === 'CERTIFICATE') {
          if (hasArrows) {
            const lines = trimmed
              .split(/\r?\n/)
              .map((l) => l.trim())
              .filter(Boolean);

            return new Handlebars.SafeString(
              `<ul class="scope-list" style="margin-left: 20px;">
                ${lines.map((l) => `<li>${l}</li>`).join('')}
              </ul>`,
            );
          }

          return new Handlebars.SafeString(
            `<div class="scope-text" style="margin-left: 18px; text-align: left; font-size: 0.85em;">${trimmed}</div>`,
          );
        }

        /* =====================================================
           DOCUMENT (Stage 1 / Stage 2) â†’ KEEP CURRENT LOGIC
        ====================================================== */

        const isLongContent = trimmed.length > 400 || trimmed.includes('\n\n');

        if (hasArrows) {
          const lines = trimmed
            .split(/\r?\n/)
            .map((l) => l.trim())
            .filter(Boolean)
            .map((l) => (l.startsWith('âž¤') ? l : `âž¤ ${l}`));

          return new Handlebars.SafeString(
            `<ul class="scope-list">
              ${lines.map((l) => `<li>${l}</li>`).join('')}
            </ul>`,
          );
        }

        if (trimmed.includes('\n')) {
          const lines = trimmed
            .split(/\r?\n/)
            .map((l) => l.trim())
            .filter(Boolean)
            .map((l) => `âž¤ ${l}`);

          return new Handlebars.SafeString(
            `<ul class="scope-list">
              ${lines.map((l) => `<li>${l}</li>`).join('')}
            </ul>`,
          );
        }

        if (isLongContent) {
          return new Handlebars.SafeString(
            `<div class="scope-list-pre">${trimmed}</div>`,
          );
        }

        const items = trimmed
          .split(/[,\\|]/)
          .map((i) => i.trim())
          .filter(Boolean)
          .map((i) => `âž¤ ${i}`);

        return new Handlebars.SafeString(
          `<ul class="scope-list">
            ${items.map((i) => `<li>${i}</li>`).join('')}
          </ul>`,
        );
      },
    );
  }
}

