import { Response, NextFunction } from 'express';
import { tenantsService } from './tenants.service.js';
import { TenantStatus } from '../auth/entities/index.js';
import { TenantPlan } from './entities/index.js';
import {
  safeValidateCreateTenant,
  safeValidateUpdateTenant,
  safeValidateUpdateTenantSettings,
} from './dto/index.js';
import {
  ApiResponse,
  AuthenticatedRequest,
  ValidationError,
  PaginationParams
} from '../../shared/types/index.js';

/**
 * TenantsController
 * Handles HTTP requests for tenant management.
 * Most endpoints require super_admin role.
 */
export class TenantsController {
  /**
   * GET /tenants - List all tenants (super_admin only)
   * Supports pagination, filtering by status/plan, and search
   */
  async findAll(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const page = parseInt(req.query.page as string) || 1;
      const limit = Math.min(parseInt(req.query.limit as string) || 20, 100);
      const sortBy = req.query.sortBy as string || 'name';
      const sortOrder = (req.query.sortOrder as 'asc' | 'desc') || 'asc';

      const params: PaginationParams = { page, limit, sortBy, sortOrder };

      // Build filter
      const filter: { status?: TenantStatus; plan?: TenantPlan; search?: string } = {};
      if (req.query.status) {
        filter.status = req.query.status as TenantStatus;
      }
      if (req.query.plan) {
        filter.plan = req.query.plan as TenantPlan;
      }
      if (req.query.search) {
        filter.search = req.query.search as string;
      }

      const result = await tenantsService.findAll(params, filter);

      const response: ApiResponse = {
        success: true,
        data: result.tenants,
        meta: {
          page,
          limit,
          total: result.total,
          totalPages: Math.ceil(result.total / limit),
        },
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /tenants/current - Get current user's tenant
   * Available to any authenticated user
   */
  async getCurrent(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.user!.tenantId;
      const tenant = await tenantsService.findById(tenantId);

      const response: ApiResponse = {
        success: true,
        data: tenant,
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /tenants/:id - Get tenant by ID (super_admin only)
   */
  async findById(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const includeSettings = req.query.includeSettings === 'true';
      const tenant = await tenantsService.findById(tenantId, includeSettings);

      const response: ApiResponse = {
        success: true,
        data: tenant,
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /tenants/:id/stats - Get tenant statistics
   */
  async getStats(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const stats = await tenantsService.getTenantStats(tenantId);

      const response: ApiResponse = {
        success: true,
        data: stats,
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /tenants - Create new tenant (super_admin only)
   */
  async create(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const validation = safeValidateCreateTenant(req.body);
      if (!validation.success) {
        throw new ValidationError('Datos invalidos', validation.error.errors);
      }

      const createdBy = req.user!.userId;
      const tenant = await tenantsService.create(validation.data, createdBy);

      const response: ApiResponse = {
        success: true,
        data: tenant,
        message: 'Tenant creado exitosamente',
      };

      res.status(201).json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * PUT /tenants/:id - Update tenant
   */
  async update(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const validation = safeValidateUpdateTenant(req.body);
      if (!validation.success) {
        throw new ValidationError('Datos invalidos', validation.error.errors);
      }

      const tenantId = req.params.id;
      const updatedBy = req.user!.userId;

      const tenant = await tenantsService.update(tenantId, validation.data, updatedBy);

      const response: ApiResponse = {
        success: true,
        data: tenant,
        message: 'Tenant actualizado exitosamente',
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /tenants/:id/suspend - Suspend tenant (super_admin only)
   */
  async suspend(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const updatedBy = req.user!.userId;

      const tenant = await tenantsService.suspend(tenantId, updatedBy);

      const response: ApiResponse = {
        success: true,
        data: tenant,
        message: 'Tenant suspendido exitosamente',
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /tenants/:id/activate - Activate tenant (super_admin only)
   */
  async activate(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const updatedBy = req.user!.userId;

      const tenant = await tenantsService.activate(tenantId, updatedBy);

      const response: ApiResponse = {
        success: true,
        data: tenant,
        message: 'Tenant activado exitosamente',
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * DELETE /tenants/:id - Soft delete tenant (super_admin only)
   * Only allowed if tenant has no active users
   */
  async delete(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const deletedBy = req.user!.userId;

      await tenantsService.delete(tenantId, deletedBy);

      const response: ApiResponse = {
        success: true,
        message: 'Tenant eliminado exitosamente',
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /tenants/:id/settings - Get tenant settings
   */
  async getSettings(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const settings = await tenantsService.getSettings(tenantId);

      const response: ApiResponse = {
        success: true,
        data: settings,
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * PUT /tenants/:id/settings - Update tenant settings
   */
  async updateSettings(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const validation = safeValidateUpdateTenantSettings(req.body);
      if (!validation.success) {
        throw new ValidationError('Datos invalidos', validation.error.errors);
      }

      const tenantId = req.params.id;
      const updatedBy = req.user!.userId;

      const settings = await tenantsService.updateSettings(
        tenantId,
        validation.data,
        updatedBy
      );

      const response: ApiResponse = {
        success: true,
        data: settings,
        message: 'Configuracion actualizada exitosamente',
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /tenants/:id/can-add-user - Check if tenant can add more users
   */
  async canAddUser(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const result = await tenantsService.canAddUser(tenantId);

      const response: ApiResponse = {
        success: true,
        data: result,
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /tenants/:id/can-use-storage - Check if tenant has available storage
   */
  async canUseStorage(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = req.params.id;
      const requiredMb = parseInt(req.query.requiredMb as string) || 0;
      const result = await tenantsService.canUseStorage(tenantId, requiredMb);

      const response: ApiResponse = {
        success: true,
        data: result,
      };

      res.json(response);
    } catch (error) {
      next(error);
    }
  }
}

export const tenantsController = new TenantsController();
