/**
 * Application Integration
 *
 * Integrates all modules and configures the application
 */

import express, { Express, Router } from 'express';
import { DataSource } from 'typeorm';

// Import modules
import { ProfilesModule } from './modules/profiles';
import { BranchesModule } from './modules/branches';
import { BillingUsageModule } from './modules/billing-usage';
import { PaymentTerminalsModule } from './modules/payment-terminals';

// Import new business modules
import { PartnersModule } from './modules/partners';
import { ProductsModule } from './modules/products';
import { WarehousesModule } from './modules/warehouses';
import { InventoryModule } from './modules/inventory';
import { SalesModule } from './modules/sales';
import { PurchasesModule } from './modules/purchases';
import { InvoicesModule } from './modules/invoices';
import { ReportsModule } from './modules/reports';
import { DashboardModule } from './modules/dashboard';
import { SettingsModule } from './modules/settings';

// Import entities from all modules for TypeORM
import {
  Person,
  UserProfile,
  ProfileTool,
  ProfileModule,
  UserProfileAssignment,
} from './modules/profiles/entities';

import {
  Device,
  BiometricCredential,
  DeviceSession,
  DeviceActivityLog,
} from './modules/biometrics/entities';

import {
  Branch,
  UserBranchAssignment,
  BranchSchedule,
  BranchPaymentTerminal,
} from './modules/branches/entities';

import {
  MobileSession,
  OfflineSyncQueue,
  PushToken,
  PaymentTransaction,
} from './modules/mobile/entities';

import {
  SubscriptionPlan,
  TenantSubscription,
  UsageTracking,
  Invoice as BillingInvoice,
  InvoiceItem as BillingInvoiceItem,
} from './modules/billing-usage/entities';

// Import entities from new business modules
import {
  Partner,
  PartnerAddress,
  PartnerContact,
  PartnerBankAccount,
} from './modules/partners/entities';

import {
  ProductCategory,
  Product,
  ProductPrice,
  ProductSupplier,
} from './modules/products/entities';

import {
  Warehouse,
  WarehouseLocation,
  WarehouseZone,
} from './modules/warehouses/entities';

import {
  StockLevel,
  StockMovement,
  InventoryCount,
  InventoryCountLine,
  TransferOrder,
  TransferOrderLine,
} from './modules/inventory/entities';

import {
  Quotation,
  QuotationItem,
  SalesOrder,
  SalesOrderItem,
} from './modules/sales/entities';

import {
  PurchaseOrder,
  PurchaseOrderItem,
  PurchaseReceipt,
  PurchaseReceiptItem,
} from './modules/purchases/entities';

import {
  Invoice,
  InvoiceItem,
  Payment,
  PaymentAllocation,
} from './modules/invoices/entities';

import {
  SystemSetting,
  PlanSetting,
  TenantSetting,
  UserPreference,
} from './modules/settings/entities';

/**
 * Get all entities for TypeORM configuration
 */
export function getAllEntities() {
  return [
    // Profiles
    Person,
    UserProfile,
    ProfileTool,
    ProfileModule,
    UserProfileAssignment,
    // Biometrics
    Device,
    BiometricCredential,
    DeviceSession,
    DeviceActivityLog,
    // Branches
    Branch,
    UserBranchAssignment,
    BranchSchedule,
    BranchPaymentTerminal,
    // Mobile
    MobileSession,
    OfflineSyncQueue,
    PushToken,
    PaymentTransaction,
    // Billing
    SubscriptionPlan,
    TenantSubscription,
    UsageTracking,
    BillingInvoice,
    BillingInvoiceItem,
    // Partners
    Partner,
    PartnerAddress,
    PartnerContact,
    PartnerBankAccount,
    // Products
    ProductCategory,
    Product,
    ProductPrice,
    ProductSupplier,
    // Warehouses
    Warehouse,
    WarehouseLocation,
    WarehouseZone,
    // Inventory
    StockLevel,
    StockMovement,
    InventoryCount,
    InventoryCountLine,
    TransferOrder,
    TransferOrderLine,
    // Sales
    Quotation,
    QuotationItem,
    SalesOrder,
    SalesOrderItem,
    // Purchases
    PurchaseOrder,
    PurchaseOrderItem,
    PurchaseReceipt,
    PurchaseReceiptItem,
    // Invoices
    Invoice,
    InvoiceItem,
    Payment,
    PaymentAllocation,
    // Settings
    SystemSetting,
    PlanSetting,
    TenantSetting,
    UserPreference,
  ];
}

/**
 * Module configuration options
 */
export interface ModuleOptions {
  profiles?: {
    enabled: boolean;
    basePath?: string;
  };
  branches?: {
    enabled: boolean;
    basePath?: string;
  };
  billing?: {
    enabled: boolean;
    basePath?: string;
  };
  payments?: {
    enabled: boolean;
    basePath?: string;
  };
  partners?: {
    enabled: boolean;
    basePath?: string;
  };
  products?: {
    enabled: boolean;
    basePath?: string;
  };
  warehouses?: {
    enabled: boolean;
    basePath?: string;
  };
  inventory?: {
    enabled: boolean;
    basePath?: string;
  };
  sales?: {
    enabled: boolean;
    basePath?: string;
  };
  purchases?: {
    enabled: boolean;
    basePath?: string;
  };
  invoices?: {
    enabled: boolean;
    basePath?: string;
  };
  reports?: {
    enabled: boolean;
    basePath?: string;
  };
  dashboard?: {
    enabled: boolean;
    basePath?: string;
  };
  settings?: {
    enabled: boolean;
    basePath?: string;
    cacheTtlMs?: number;
  };
}

/**
 * Default module options
 */
const defaultModuleOptions: ModuleOptions = {
  profiles: { enabled: true, basePath: '/api' },
  branches: { enabled: true, basePath: '/api' },
  billing: { enabled: true, basePath: '/api' },
  payments: { enabled: true, basePath: '/api' },
  partners: { enabled: true, basePath: '/api' },
  products: { enabled: true, basePath: '/api' },
  warehouses: { enabled: true, basePath: '/api' },
  inventory: { enabled: true, basePath: '/api' },
  sales: { enabled: true, basePath: '/api' },
  purchases: { enabled: true, basePath: '/api' },
  invoices: { enabled: true, basePath: '/api' },
  reports: { enabled: true, basePath: '/api' },
  dashboard: { enabled: true, basePath: '/api' },
  settings: { enabled: true, basePath: '/api/v1' },
};

/**
 * Initialize and integrate all modules
 */
export function initializeModules(
  app: Express,
  dataSource: DataSource,
  options: ModuleOptions = {}
): void {
  const config = { ...defaultModuleOptions, ...options };

  // Initialize Profiles Module
  if (config.profiles?.enabled) {
    const profilesModule = new ProfilesModule({
      dataSource,
      basePath: config.profiles.basePath,
    });
    app.use(profilesModule.router);
    console.log('✅ Profiles module initialized');
  }

  // Initialize Branches Module
  if (config.branches?.enabled) {
    const branchesModule = new BranchesModule({
      dataSource,
      basePath: config.branches.basePath,
    });
    app.use(branchesModule.router);
    console.log('✅ Branches module initialized');
  }

  // Initialize Billing Module
  if (config.billing?.enabled) {
    const billingModule = new BillingUsageModule({
      dataSource,
      basePath: config.billing.basePath,
    });
    app.use(billingModule.router);
    console.log('✅ Billing module initialized');
  }

  // Initialize Payment Terminals Module
  if (config.payments?.enabled) {
    const paymentModule = new PaymentTerminalsModule({
      dataSource,
      basePath: config.payments.basePath,
    });
    app.use(paymentModule.router);
    console.log('✅ Payment Terminals module initialized');
  }

  // Initialize Partners Module
  if (config.partners?.enabled) {
    const partnersModule = new PartnersModule({
      dataSource,
      basePath: config.partners.basePath,
    });
    app.use(partnersModule.router);
    console.log('✅ Partners module initialized');
  }

  // Initialize Products Module
  if (config.products?.enabled) {
    const productsModule = new ProductsModule({
      dataSource,
      basePath: config.products.basePath,
    });
    app.use(productsModule.router);
    console.log('✅ Products module initialized');
  }

  // Initialize Warehouses Module
  if (config.warehouses?.enabled) {
    const warehousesModule = new WarehousesModule({
      dataSource,
      basePath: config.warehouses.basePath,
    });
    app.use(warehousesModule.router);
    console.log('✅ Warehouses module initialized');
  }

  // Initialize Inventory Module
  if (config.inventory?.enabled) {
    const inventoryModule = new InventoryModule({
      dataSource,
      basePath: config.inventory.basePath,
    });
    app.use(inventoryModule.router);
    console.log('✅ Inventory module initialized');
  }

  // Initialize Sales Module
  if (config.sales?.enabled) {
    const salesModule = new SalesModule({
      dataSource,
      basePath: config.sales.basePath,
    });
    app.use(salesModule.router);
    console.log('✅ Sales module initialized');
  }

  // Initialize Purchases Module
  if (config.purchases?.enabled) {
    const purchasesModule = new PurchasesModule({
      dataSource,
      basePath: config.purchases.basePath,
    });
    app.use(purchasesModule.router);
    console.log('✅ Purchases module initialized');
  }

  // Initialize Invoices Module
  // Note: Invoices now uses routes-based approach via invoices.routes.ts in app.ts
  if (config.invoices?.enabled) {
    const invoicesModuleInstance = new InvoicesModule();
    app.use(invoicesModuleInstance.router);
    console.log('✅ Invoices module initialized');
  }

  // Initialize Reports Module
  if (config.reports?.enabled) {
    const reportsModule = new ReportsModule({
      dataSource,
      basePath: config.reports.basePath,
    });
    app.use(reportsModule.router);
    console.log('✅ Reports module initialized');
  }

  // Initialize Dashboard Module
  if (config.dashboard?.enabled) {
    const dashboardModule = new DashboardModule({
      dataSource,
      basePath: config.dashboard.basePath,
    });
    app.use(dashboardModule.router);
    console.log('✅ Dashboard module initialized');
  }

  // Initialize Settings Module
  if (config.settings?.enabled) {
    const settingsModule = new SettingsModule({
      dataSource,
      basePath: config.settings.basePath,
      cacheTtlMs: config.settings.cacheTtlMs,
    });
    app.use(settingsModule.router);
    console.log('✅ Settings module initialized');
  }
}

/**
 * Create TypeORM DataSource configuration
 */
export function createDataSourceConfig(options: {
  host: string;
  port: number;
  username: string;
  password: string;
  database: string;
  ssl?: boolean;
  logging?: boolean;
}) {
  return {
    type: 'postgres' as const,
    host: options.host,
    port: options.port,
    username: options.username,
    password: options.password,
    database: options.database,
    ssl: options.ssl ? { rejectUnauthorized: false } : false,
    logging: options.logging ?? false,
    entities: getAllEntities(),
    synchronize: false, // Use migrations instead
    migrations: ['src/migrations/*.ts'],
  };
}

/**
 * Example application setup
 */
export async function createApplication(dataSourceConfig: any): Promise<Express> {
  // Create Express app
  const app = express();

  // Middleware
  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));

  // CORS middleware (configure for production)
  app.use((req, res, next) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Tenant-ID');
    if (req.method === 'OPTIONS') {
      res.sendStatus(200);
      return;
    }
    next();
  });

  // Initialize database
  const dataSource = new DataSource(dataSourceConfig);
  await dataSource.initialize();
  console.log('✅ Database connected');

  // Initialize all modules
  initializeModules(app, dataSource);

  // Health check endpoint
  app.get('/health', (req, res) => {
    res.json({
      status: 'healthy',
      timestamp: new Date().toISOString(),
      modules: {
        profiles: true,
        branches: true,
        billing: true,
        payments: true,
        partners: true,
        products: true,
        warehouses: true,
        inventory: true,
        sales: true,
        purchases: true,
        invoices: true,
        reports: true,
        dashboard: true,
        settings: true,
      },
    });
  });

  // Error handling middleware
  app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
    console.error('Error:', err);
    res.status(err.status || 500).json({
      error: err.message || 'Internal Server Error',
      code: err.code || 'INTERNAL_ERROR',
    });
  });

  return app;
}

export default {
  getAllEntities,
  initializeModules,
  createDataSourceConfig,
  createApplication,
};
