import { Request, Response, NextFunction } from 'express';
import { SaasTenantService } from '../services/tenant/SaasTenantService';
import { logger } from '../utils/logger';

declare global {
  namespace Express {
    interface Request {
      tenant?: {
        id: string;
        code: string;
        name: string;
        type: string;
        status: string;
        plan: string;
      };
      tenantId?: string;
    }
  }
}

export class TenantDomainMiddleware {
  private static readonly MAIN_DOMAIN = process.env.MAIN_DOMAIN || 'platform.com';
  private static readonly ADMIN_SUBDOMAIN = process.env.ADMIN_SUBDOMAIN || 'admin';
  private static readonly API_SUBDOMAIN = process.env.API_SUBDOMAIN || 'api';

  static async resolveTenant(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const host = req.headers.host?.split(':')[0];
      
      if (!host) {
        res.status(400).json({ error: 'Missing host header' });
        return;
      }

      logger.debug(`[TenantDomain] Resolving tenant for host: ${host}`);

      if (host === this.MAIN_DOMAIN || host.startsWith(`${this.ADMIN_SUBDOMAIN}.`) || host.startsWith(`${this.API_SUBDOMAIN}.`)) {
        logger.debug('[TenantDomain] Main domain or admin/api subdomain, skipping tenant resolution');
        return next();
      }

      if (host.endsWith(`.${this.MAIN_DOMAIN}`)) {
        const subdomain = host.replace(`.${this.MAIN_DOMAIN}`, '');
        
        if (subdomain === this.ADMIN_SUBDOMAIN || subdomain === this.API_SUBDOMAIN) {
          logger.debug('[TenantDomain] Admin or API subdomain, skipping tenant resolution');
          return next();
        }

        const tenant = await SaasTenantService.getTenantByCode(subdomain);
        
        if (tenant && tenant.status === 'ACTIVE') {
          req.tenant = {
            id: tenant.id,
            code: tenant.code,
            name: tenant.name,
            type: tenant.type,
            status: tenant.status,
            plan: tenant.plan,
          };
          req.tenantId = tenant.id;
          
          logger.info(`[TenantDomain] Tenant resolved: ${tenant.code} (${tenant.id})`);
        } else {
          logger.warn(`[TenantDomain] Tenant not found or inactive: ${subdomain}`);
        }
      } else {
        const tenant = await SaasTenantService.getTenantByDomain(host);
        
        if (tenant && tenant.status === 'ACTIVE') {
          req.tenant = {
            id: tenant.id,
            code: tenant.code,
            name: tenant.name,
            type: tenant.type,
            status: tenant.status,
            plan: tenant.plan,
          };
          req.tenantId = tenant.id;
          
          logger.info(`[TenantDomain] Tenant resolved by custom domain: ${host} -> ${tenant.code} (${tenant.id})`);
        } else {
          logger.warn(`[TenantDomain] Custom domain not found or inactive: ${host}`);
        }
      }

      next();
    } catch (error) {
      logger.error('[TenantDomain] Error resolving tenant:', error);
      next();
    }
  }

  static requireTenant(req: Request, res: Response, next: NextFunction): void {
    if (!req.tenant) {
      res.status(404).json({ error: 'Tenant not found' });
      return;
    }
    next();
  }

  static requireAdmin(req: Request, res: Response, next: NextFunction): void {
    const host = req.headers.host?.split(':')[0];
    
    if (!host) {
      res.status(400).json({ error: 'Missing host header' });
      return;
    }

    if (host === this.MAIN_DOMAIN || host.startsWith(`${this.ADMIN_SUBDOMAIN}.`)) {
      next();
      return;
    }

    res.status(403).json({ error: 'Admin access only' });
  }
}