import { Response, NextFunction } from 'express';
import { z } from 'zod';
import { pricelistsService, CreatePricelistDto, UpdatePricelistDto, CreatePricelistItemDto, PricelistFilters } from './pricelists.service.js';
import { salesTeamsService, CreateSalesTeamDto, UpdateSalesTeamDto, SalesTeamFilters } from './sales-teams.service.js';
import { customerGroupsService, CreateCustomerGroupDto, UpdateCustomerGroupDto, CustomerGroupFilters } from './customer-groups.service.js';
import { quotationsService, CreateQuotationDto, UpdateQuotationDto, CreateQuotationLineDto, UpdateQuotationLineDto, QuotationFilters } from './quotations.service.js';
import { ordersService, CreateSalesOrderDto, UpdateSalesOrderDto, CreateSalesOrderLineDto, UpdateSalesOrderLineDto, SalesOrderFilters } from './orders.service.js';
import { AuthenticatedRequest } from '../../shared/middleware/auth.middleware.js';
import { ValidationError } from '../../shared/errors/index.js';

// Pricelist schemas
const createPricelistSchema = z.object({
  company_id: z.string().uuid().optional(),
  name: z.string().min(1, 'El nombre es requerido').max(255),
  currency_id: z.string().uuid({ message: 'La moneda es requerida' }),
});

const updatePricelistSchema = z.object({
  name: z.string().min(1).max(255).optional(),
  currency_id: z.string().uuid().optional(),
  active: z.boolean().optional(),
});

const createPricelistItemSchema = z.object({
  product_id: z.string().uuid().optional(),
  product_category_id: z.string().uuid().optional(),
  price: z.number().min(0, 'El precio debe ser positivo'),
  min_quantity: z.number().positive().default(1),
  valid_from: z.string().optional(),
  valid_to: z.string().optional(),
});

const pricelistQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  active: z.coerce.boolean().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

// Sales Team schemas
const createSalesTeamSchema = z.object({
  company_id: z.string().uuid({ message: 'La empresa es requerida' }),
  name: z.string().min(1, 'El nombre es requerido').max(255),
  code: z.string().max(50).optional(),
  team_leader_id: z.string().uuid().optional(),
  target_monthly: z.number().positive().optional(),
  target_annual: z.number().positive().optional(),
});

const updateSalesTeamSchema = z.object({
  name: z.string().min(1).max(255).optional(),
  code: z.string().max(50).optional(),
  team_leader_id: z.string().uuid().optional().nullable(),
  target_monthly: z.number().positive().optional().nullable(),
  target_annual: z.number().positive().optional().nullable(),
  active: z.boolean().optional(),
});

const addTeamMemberSchema = z.object({
  user_id: z.string().uuid({ message: 'El usuario es requerido' }),
  role: z.string().max(100).default('member'),
});

const salesTeamQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  active: z.coerce.boolean().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

// Customer Group schemas
const createCustomerGroupSchema = z.object({
  name: z.string().min(1, 'El nombre es requerido').max(255),
  description: z.string().optional(),
  discount_percentage: z.number().min(0).max(100).default(0),
});

const updateCustomerGroupSchema = z.object({
  name: z.string().min(1).max(255).optional(),
  description: z.string().optional().nullable(),
  discount_percentage: z.number().min(0).max(100).optional(),
});

const addGroupMemberSchema = z.object({
  partner_id: z.string().uuid({ message: 'El cliente es requerido' }),
});

const customerGroupQuerySchema = z.object({
  search: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

// Quotation schemas
const createQuotationSchema = z.object({
  company_id: z.string().uuid({ message: 'La empresa es requerida' }),
  partner_id: z.string().uuid({ message: 'El cliente es requerido' }),
  quotation_date: z.string().optional(),
  validity_date: z.string({ message: 'La fecha de validez es requerida' }),
  currency_id: z.string().uuid({ message: 'La moneda es requerida' }),
  pricelist_id: z.string().uuid().optional(),
  sales_team_id: z.string().uuid().optional(),
  notes: z.string().optional(),
  terms_conditions: z.string().optional(),
});

const updateQuotationSchema = z.object({
  partner_id: z.string().uuid().optional(),
  quotation_date: z.string().optional(),
  validity_date: z.string().optional(),
  currency_id: z.string().uuid().optional(),
  pricelist_id: z.string().uuid().optional().nullable(),
  sales_team_id: z.string().uuid().optional().nullable(),
  notes: z.string().optional().nullable(),
  terms_conditions: z.string().optional().nullable(),
});

const createQuotationLineSchema = z.object({
  product_id: z.string().uuid().optional(),
  description: z.string().min(1, 'La descripción es requerida'),
  quantity: z.number().positive('La cantidad debe ser positiva'),
  uom_id: z.string().uuid({ message: 'La unidad de medida es requerida' }),
  price_unit: z.number().min(0, 'El precio debe ser positivo'),
  discount: z.number().min(0).max(100).default(0),
  tax_ids: z.array(z.string().uuid()).optional(),
});

const updateQuotationLineSchema = z.object({
  description: z.string().min(1).optional(),
  quantity: z.number().positive().optional(),
  uom_id: z.string().uuid().optional(),
  price_unit: z.number().min(0).optional(),
  discount: z.number().min(0).max(100).optional(),
  tax_ids: z.array(z.string().uuid()).optional(),
});

const quotationQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  partner_id: z.string().uuid().optional(),
  status: z.enum(['draft', 'sent', 'confirmed', 'cancelled', 'expired']).optional(),
  date_from: z.string().optional(),
  date_to: z.string().optional(),
  search: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

// Sales Order schemas
const createSalesOrderSchema = z.object({
  company_id: z.string().uuid({ message: 'La empresa es requerida' }),
  partner_id: z.string().uuid({ message: 'El cliente es requerido' }),
  client_order_ref: z.string().max(100).optional(),
  order_date: z.string().optional(),
  validity_date: z.string().optional(),
  commitment_date: z.string().optional(),
  currency_id: z.string().uuid({ message: 'La moneda es requerida' }),
  pricelist_id: z.string().uuid().optional(),
  payment_term_id: z.string().uuid().optional(),
  sales_team_id: z.string().uuid().optional(),
  invoice_policy: z.enum(['order', 'delivery']).default('order'),
  notes: z.string().optional(),
  terms_conditions: z.string().optional(),
});

const updateSalesOrderSchema = z.object({
  partner_id: z.string().uuid().optional(),
  client_order_ref: z.string().max(100).optional().nullable(),
  order_date: z.string().optional(),
  validity_date: z.string().optional().nullable(),
  commitment_date: z.string().optional().nullable(),
  currency_id: z.string().uuid().optional(),
  pricelist_id: z.string().uuid().optional().nullable(),
  payment_term_id: z.string().uuid().optional().nullable(),
  sales_team_id: z.string().uuid().optional().nullable(),
  invoice_policy: z.enum(['order', 'delivery']).optional(),
  notes: z.string().optional().nullable(),
  terms_conditions: z.string().optional().nullable(),
});

const createSalesOrderLineSchema = z.object({
  product_id: z.string().uuid({ message: 'El producto es requerido' }),
  description: z.string().min(1, 'La descripción es requerida'),
  quantity: z.number().positive('La cantidad debe ser positiva'),
  uom_id: z.string().uuid({ message: 'La unidad de medida es requerida' }),
  price_unit: z.number().min(0, 'El precio debe ser positivo'),
  discount: z.number().min(0).max(100).default(0),
  tax_ids: z.array(z.string().uuid()).optional(),
  analytic_account_id: z.string().uuid().optional(),
});

const updateSalesOrderLineSchema = z.object({
  description: z.string().min(1).optional(),
  quantity: z.number().positive().optional(),
  uom_id: z.string().uuid().optional(),
  price_unit: z.number().min(0).optional(),
  discount: z.number().min(0).max(100).optional(),
  tax_ids: z.array(z.string().uuid()).optional(),
  analytic_account_id: z.string().uuid().optional().nullable(),
});

const salesOrderQuerySchema = z.object({
  company_id: z.string().uuid().optional(),
  partner_id: z.string().uuid().optional(),
  status: z.enum(['draft', 'sent', 'sale', 'done', 'cancelled']).optional(),
  invoice_status: z.enum(['pending', 'partial', 'invoiced']).optional(),
  delivery_status: z.enum(['pending', 'partial', 'delivered']).optional(),
  date_from: z.string().optional(),
  date_to: z.string().optional(),
  search: z.string().optional(),
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().positive().max(100).default(20),
});

class SalesController {
  // ========== PRICELISTS ==========
  async getPricelists(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = pricelistQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parámetros de consulta inválidos', queryResult.error.errors);
      }

      const filters: PricelistFilters = queryResult.data;
      const result = await pricelistsService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: filters.page,
          limit: filters.limit,
          totalPages: Math.ceil(result.total / (filters.limit || 20)),
        },
      });
    } catch (error) {
      next(error);
    }
  }

  async getPricelist(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const pricelist = await pricelistsService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: pricelist });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: CreatePricelistDto = parseResult.data;
      const pricelist = await pricelistsService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: pricelist,
        message: 'Lista de precios creada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: UpdatePricelistDto = parseResult.data;
      const pricelist = await pricelistsService.update(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.json({
        success: true,
        data: pricelist,
        message: 'Lista de precios actualizada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: CreatePricelistItemDto = parseResult.data;
      const item = await pricelistsService.addItem(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: item,
        message: 'Item agregado exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async removePricelistItem(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await pricelistsService.removeItem(req.params.id, req.params.itemId, req.tenantId!);
      res.json({ success: true, message: 'Item eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  // ========== SALES TEAMS ==========
  async getSalesTeams(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = salesTeamQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parámetros de consulta inválidos', queryResult.error.errors);
      }

      const filters: SalesTeamFilters = queryResult.data;
      const result = await salesTeamsService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: filters.page,
          limit: filters.limit,
          totalPages: Math.ceil(result.total / (filters.limit || 20)),
        },
      });
    } catch (error) {
      next(error);
    }
  }

  async getSalesTeam(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const team = await salesTeamsService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: team });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: CreateSalesTeamDto = parseResult.data;
      const team = await salesTeamsService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: team,
        message: 'Equipo de ventas creado exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: UpdateSalesTeamDto = parseResult.data;
      const team = await salesTeamsService.update(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.json({
        success: true,
        data: team,
        message: 'Equipo de ventas actualizado exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

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

      const member = await salesTeamsService.addMember(
        req.params.id,
        parseResult.data.user_id,
        parseResult.data.role,
        req.tenantId!
      );

      res.status(201).json({
        success: true,
        data: member,
        message: 'Miembro agregado exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async removeSalesTeamMember(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await salesTeamsService.removeMember(req.params.id, req.params.memberId, req.tenantId!);
      res.json({ success: true, message: 'Miembro eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  // ========== CUSTOMER GROUPS ==========
  async getCustomerGroups(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = customerGroupQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parámetros de consulta inválidos', queryResult.error.errors);
      }

      const filters: CustomerGroupFilters = queryResult.data;
      const result = await customerGroupsService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: filters.page,
          limit: filters.limit,
          totalPages: Math.ceil(result.total / (filters.limit || 20)),
        },
      });
    } catch (error) {
      next(error);
    }
  }

  async getCustomerGroup(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const group = await customerGroupsService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: group });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: CreateCustomerGroupDto = parseResult.data;
      const group = await customerGroupsService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: group,
        message: 'Grupo de clientes creado exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: UpdateCustomerGroupDto = parseResult.data;
      const group = await customerGroupsService.update(req.params.id, dto, req.tenantId!);

      res.json({
        success: true,
        data: group,
        message: 'Grupo de clientes actualizado exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async deleteCustomerGroup(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await customerGroupsService.delete(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Grupo de clientes eliminado exitosamente' });
    } catch (error) {
      next(error);
    }
  }

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

      const member = await customerGroupsService.addMember(
        req.params.id,
        parseResult.data.partner_id,
        req.tenantId!
      );

      res.status(201).json({
        success: true,
        data: member,
        message: 'Cliente agregado al grupo exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async removeCustomerGroupMember(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await customerGroupsService.removeMember(req.params.id, req.params.memberId, req.tenantId!);
      res.json({ success: true, message: 'Cliente eliminado del grupo exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  // ========== QUOTATIONS ==========
  async getQuotations(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = quotationQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parámetros de consulta inválidos', queryResult.error.errors);
      }

      const filters: QuotationFilters = queryResult.data;
      const result = await quotationsService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: filters.page,
          limit: filters.limit,
          totalPages: Math.ceil(result.total / (filters.limit || 20)),
        },
      });
    } catch (error) {
      next(error);
    }
  }

  async getQuotation(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const quotation = await quotationsService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: quotation });
    } catch (error) {
      next(error);
    }
  }

  async createQuotation(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createQuotationSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de cotización inválidos', parseResult.error.errors);
      }

      const dto: CreateQuotationDto = parseResult.data;
      const quotation = await quotationsService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: quotation,
        message: 'Cotización creada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async updateQuotation(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateQuotationSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de cotización inválidos', parseResult.error.errors);
      }

      const dto: UpdateQuotationDto = parseResult.data;
      const quotation = await quotationsService.update(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.json({
        success: true,
        data: quotation,
        message: 'Cotización actualizada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async deleteQuotation(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await quotationsService.delete(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Cotización eliminada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async addQuotationLine(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createQuotationLineSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de línea inválidos', parseResult.error.errors);
      }

      const dto: CreateQuotationLineDto = parseResult.data;
      const line = await quotationsService.addLine(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: line,
        message: 'Línea agregada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async updateQuotationLine(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateQuotationLineSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de línea inválidos', parseResult.error.errors);
      }

      const dto: UpdateQuotationLineDto = parseResult.data;
      const line = await quotationsService.updateLine(req.params.id, req.params.lineId, dto, req.tenantId!);

      res.json({
        success: true,
        data: line,
        message: 'Línea actualizada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async removeQuotationLine(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await quotationsService.removeLine(req.params.id, req.params.lineId, req.tenantId!);
      res.json({ success: true, message: 'Línea eliminada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async sendQuotation(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const quotation = await quotationsService.send(req.params.id, req.tenantId!, req.user!.userId);
      res.json({
        success: true,
        data: quotation,
        message: 'Cotización enviada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async confirmQuotation(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const result = await quotationsService.confirm(req.params.id, req.tenantId!, req.user!.userId);
      res.json({
        success: true,
        data: result.quotation,
        orderId: result.orderId,
        message: 'Cotización confirmada y orden de venta creada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async cancelQuotation(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const quotation = await quotationsService.cancel(req.params.id, req.tenantId!, req.user!.userId);
      res.json({
        success: true,
        data: quotation,
        message: 'Cotización cancelada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  // ========== SALES ORDERS ==========
  async getOrders(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const queryResult = salesOrderQuerySchema.safeParse(req.query);
      if (!queryResult.success) {
        throw new ValidationError('Parámetros de consulta inválidos', queryResult.error.errors);
      }

      const filters: SalesOrderFilters = queryResult.data;
      const result = await ordersService.findAll(req.tenantId!, filters);

      res.json({
        success: true,
        data: result.data,
        meta: {
          total: result.total,
          page: filters.page,
          limit: filters.limit,
          totalPages: Math.ceil(result.total / (filters.limit || 20)),
        },
      });
    } catch (error) {
      next(error);
    }
  }

  async getOrder(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const order = await ordersService.findById(req.params.id, req.tenantId!);
      res.json({ success: true, data: order });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: CreateSalesOrderDto = parseResult.data;
      const order = await ordersService.create(dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: order,
        message: 'Orden de venta creada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

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

      const dto: UpdateSalesOrderDto = parseResult.data;
      const order = await ordersService.update(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.json({
        success: true,
        data: order,
        message: 'Orden de venta actualizada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async deleteOrder(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await ordersService.delete(req.params.id, req.tenantId!);
      res.json({ success: true, message: 'Orden de venta eliminada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async addOrderLine(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = createSalesOrderLineSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de línea inválidos', parseResult.error.errors);
      }

      const dto: CreateSalesOrderLineDto = parseResult.data;
      const line = await ordersService.addLine(req.params.id, dto, req.tenantId!, req.user!.userId);

      res.status(201).json({
        success: true,
        data: line,
        message: 'Línea agregada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async updateOrderLine(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const parseResult = updateSalesOrderLineSchema.safeParse(req.body);
      if (!parseResult.success) {
        throw new ValidationError('Datos de línea inválidos', parseResult.error.errors);
      }

      const dto: UpdateSalesOrderLineDto = parseResult.data;
      const line = await ordersService.updateLine(req.params.id, req.params.lineId, dto, req.tenantId!);

      res.json({
        success: true,
        data: line,
        message: 'Línea actualizada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async removeOrderLine(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      await ordersService.removeLine(req.params.id, req.params.lineId, req.tenantId!);
      res.json({ success: true, message: 'Línea eliminada exitosamente' });
    } catch (error) {
      next(error);
    }
  }

  async confirmOrder(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const order = await ordersService.confirm(req.params.id, req.tenantId!, req.user!.userId);
      res.json({
        success: true,
        data: order,
        message: 'Orden de venta confirmada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async cancelOrder(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const order = await ordersService.cancel(req.params.id, req.tenantId!, req.user!.userId);
      res.json({
        success: true,
        data: order,
        message: 'Orden de venta cancelada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }

  async createOrderInvoice(req: AuthenticatedRequest, res: Response, next: NextFunction): Promise<void> {
    try {
      const result = await ordersService.createInvoice(req.params.id, req.tenantId!, req.user!.userId);
      res.status(201).json({
        success: true,
        data: result,
        message: 'Factura creada exitosamente',
      });
    } catch (error) {
      next(error);
    }
  }
}

export const salesController = new SalesController();
