import { Request, Response, NextFunction } from 'express';
import { z } from 'zod';
import { authService } from './auth.service.js';
import { ApiResponse, AuthenticatedRequest, ValidationError } from '../../shared/types/index.js';

// Validation schemas
const loginSchema = z.object({
  email: z.string().email('Email inválido'),
  password: z.string().min(6, 'La contraseña debe tener al menos 6 caracteres'),
});

const registerSchema = z.object({
  email: z.string().email('Email inválido'),
  password: z.string().min(8, 'La contraseña debe tener al menos 8 caracteres'),
  // Soporta ambos formatos: full_name (legacy) o firstName+lastName (frontend)
  full_name: z.string().min(2, 'El nombre debe tener al menos 2 caracteres').optional(),
  firstName: z.string().min(2, 'Nombre debe tener al menos 2 caracteres').optional(),
  lastName: z.string().min(2, 'Apellido debe tener al menos 2 caracteres').optional(),
  tenant_id: z.string().uuid('Tenant ID inválido').optional(),
  companyName: z.string().optional(),
}).refine(
  (data) => data.full_name || (data.firstName && data.lastName),
  { message: 'Se requiere full_name o firstName y lastName', path: ['full_name'] }
);

const changePasswordSchema = z.object({
  current_password: z.string().min(1, 'Contraseña actual requerida'),
  new_password: z.string().min(8, 'La nueva contraseña debe tener al menos 8 caracteres'),
});

const refreshTokenSchema = z.object({
  refresh_token: z.string().min(1, 'Refresh token requerido'),
});

export class AuthController {
  async login(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const validation = loginSchema.safeParse(req.body);
      if (!validation.success) {
        throw new ValidationError('Datos inválidos', validation.error.errors);
      }

      const result = await authService.login(validation.data);

      const response: ApiResponse = {
        success: true,
        data: result,
        message: 'Inicio de sesión exitoso',
      };

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

  async register(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const validation = registerSchema.safeParse(req.body);
      if (!validation.success) {
        throw new ValidationError('Datos inválidos', validation.error.errors);
      }

      const result = await authService.register(validation.data);

      const response: ApiResponse = {
        success: true,
        data: result,
        message: 'Usuario registrado exitosamente',
      };

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

  async refreshToken(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const validation = refreshTokenSchema.safeParse(req.body);
      if (!validation.success) {
        throw new ValidationError('Datos inválidos', validation.error.errors);
      }

      const tokens = await authService.refreshToken(validation.data.refresh_token);

      const response: ApiResponse = {
        success: true,
        data: { tokens },
        message: 'Token renovado exitosamente',
      };

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

  async changePassword(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const validation = changePasswordSchema.safeParse(req.body);
      if (!validation.success) {
        throw new ValidationError('Datos inválidos', validation.error.errors);
      }

      const userId = req.user!.userId;
      await authService.changePassword(
        userId,
        validation.data.current_password,
        validation.data.new_password
      );

      const response: ApiResponse = {
        success: true,
        message: 'Contraseña actualizada exitosamente',
      };

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

  async getProfile(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const userId = req.user!.userId;
      const profile = await authService.getProfile(userId);

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

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

  async logout(_req: AuthenticatedRequest, res: Response): Promise<void> {
    // For JWT, logout is handled client-side by removing the token
    // Here we could add token to a blacklist if needed
    const response: ApiResponse = {
      success: true,
      message: 'Sesión cerrada exitosamente',
    };

    res.json(response);
  }
}

export const authController = new AuthController();
