import type { Request, Response, NextFunction } from 'express';
import * as trialInvitationService from '../services/trial-invitations.service.js';
import { hasAnyPlatformRole } from '../utils/platform-admin.js';
import { prisma } from '../config/database.js';

async function requireAdminOrSales(req: Request, res: Response): Promise<boolean> {
  const isAdmin = await hasAnyPlatformRole(req.user!.userId, 'platform_admin', 'platform_sales');
  if (!isAdmin) {
    res.status(403).json({ message: 'Solo administradores o vendedores pueden gestionar invitaciones de trial' });
  }
  return isAdmin;
}

export async function createInvitation(req: Request, res: Response, next: NextFunction) {
  try {
    if (!(await requireAdminOrSales(req, res))) return;

    const { tenantId, plan, durationDays } = req.body;
    if (!tenantId || !durationDays || durationDays < 1 || durationDays > 365) {
      return res.status(400).json({ message: 'tenantId y durationDays (1-365) son requeridos' });
    }

    const invitation = await trialInvitationService.createInvitation({
      tenantId,
      invitedByUserId: req.user!.userId,
      plan: plan || 'business_control',
      durationDays: parseInt(durationDays, 10),
    });

    res.status(201).json(invitation);
  } catch (error: any) {
    if (error.message?.includes('ya tiene') || error.message?.includes('no encontrado')) {
      return res.status(400).json({ message: error.message });
    }
    next(error);
  }
}

export async function getAllInvitations(req: Request, res: Response, next: NextFunction) {
  try {
    if (!(await requireAdminOrSales(req, res))) return;

    const { tenantId, status } = req.query;
    const invitations = await trialInvitationService.getInvitations({
      tenantId: typeof tenantId === 'string' ? tenantId : undefined,
      status: typeof status === 'string' ? status : undefined,
    });

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

export async function getMyPendingInvitation(req: Request, res: Response, next: NextFunction) {
  try {
    const invitation = await trialInvitationService.getPendingInvitationForTenant(req.user!.tenantId);
    res.json(invitation);
  } catch (error) {
    next(error);
  }
}

export async function acceptInvitation(req: Request, res: Response, next: NextFunction) {
  try {
    const token = typeof req.params.token === 'string' ? req.params.token : '';
    if (!token) {
      return res.status(400).json({ message: 'Token requerido' });
    }

    const result = await trialInvitationService.acceptInvitation(token, req.user!.userId);
    res.json(result);
  } catch (error: any) {
    if (
      error.message?.includes('no encontrada') ||
      error.message?.includes('ya ') ||
      error.message?.includes('expirado') ||
      error.message?.includes('Solo el dueño')
    ) {
      return res.status(400).json({ message: error.message });
    }
    next(error);
  }
}

export async function cancelInvitation(req: Request, res: Response, next: NextFunction) {
  try {
    if (!(await requireAdminOrSales(req, res))) return;

    const id = typeof req.params.id === 'string' ? req.params.id : '';
    const result = await trialInvitationService.cancelInvitation(id);
    res.json(result);
  } catch (error: any) {
    if (error.message?.includes('no encontrada') || error.message?.includes('Solo se pueden')) {
      return res.status(400).json({ message: error.message });
    }
    next(error);
  }
}

export async function getInvitationByToken(req: Request, res: Response, next: NextFunction) {
  try {
    const token = typeof req.params.token === 'string' ? req.params.token : '';
    const invitation = await prisma.trialInvitation.findUnique({
      where: { token },
    });

    if (!invitation) {
      return res.status(404).json({ message: 'Invitación no encontrada' });
    }

    const tenant = await prisma.tenant.findUnique({
      where: { id: invitation.tenantId },
      select: { nombre: true, rfc: true },
    });

    // No exponer datos sensibles
    res.json({
      id: invitation.id,
      tenantId: invitation.tenantId,
      plan: invitation.plan,
      durationDays: invitation.durationDays,
      status: invitation.status,
      expiresAt: invitation.expiresAt,
      tenant,
    });
  } catch (error) {
    next(error);
  }
}
