import { Injectable, NotFoundException, Logger } from '@nestjs/common';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreateProductoPrecioCuotaDto } from './dto/create-producto-precio-cuota.dto';
import { UpdateProductoPrecioCuotaDto } from './dto/update-producto-precio-cuota.dto';

@Injectable()
export class ProductoPrecioCuotasService {
  private readonly logger = new Logger(ProductoPrecioCuotasService.name);
  constructor(
    private prisma: PrismaService,
  ) {}

  // ==================== CREAR ====================

  async create(dto: CreateProductoPrecioCuotaDto, empresaId: string, usuario?: string) {
    // Validar que el producto exista y pertenezca a la empresa
    const producto = await this.prisma.productos.findFirst({
      where: { id: dto.producto_id, empresa_id: empresaId },
      select: { id: true, descripcion: true },
    });

    if (!producto) {
      throw new NotFoundException('Producto no encontrado o no pertenece a la empresa');
    }

    // Calcular monto_total = cant_cuotas * monto_cuota
    const montoTotal = dto.cant_cuotas * dto.monto_cuota;

    const registro = await this.prisma.producto_precio_cuota.create({
      data: {
        empresa_id: empresaId,
        producto_id: dto.producto_id,
        nombre: dto.nombre,
        cant_cuotas: dto.cant_cuotas,
        monto_cuota: dto.monto_cuota,
        monto_total: montoTotal,
        cuota_inicial: dto.cuota_inicial ?? null,
        descuento_porcentaje: dto.descuento_porcentaje ?? 0,
        moneda: dto.moneda ?? 'PYG',
        activo: dto.activo ?? true,
        orden: dto.orden ?? 0,
        usuario: usuario ?? null,
      },
    });

    this.logger.log(
      `Precio cuota creado: "${registro.nombre}" para producto ${producto.descripcion} (${registro.id})`,
      'ProductoPrecioCuotasService',
    );

    return registro;
  }

  // ==================== LISTAR POR PRODUCTO ====================

  async findByProducto(productoId: string, empresaId: string) {
    return this.prisma.producto_precio_cuota.findMany({
      where: {
        producto_id: productoId,
        empresa_id: empresaId,
      },
      orderBy: [{ orden: 'asc' }, { cant_cuotas: 'asc' }],
    });
  }

  // ==================== BULK: OBTENER POR MÚLTIPLES PRODUCTOS (para POS) ====================

  async findByProductos(productoIds: string[], empresaId: string) {
    if (!productoIds || productoIds.length === 0) {
      return [];
    }

    const registros = await this.prisma.producto_precio_cuota.findMany({
      where: {
        producto_id: { in: productoIds },
        empresa_id: empresaId,
        activo: true,
      },
      orderBy: [{ orden: 'asc' }, { cant_cuotas: 'asc' }],
    });

    // Agrupar por producto_id para facilitar el consumo en frontend
    const agrupado: Record<string, typeof registros> = {};
    for (const reg of registros) {
      if (!agrupado[reg.producto_id]) {
        agrupado[reg.producto_id] = [];
      }
      agrupado[reg.producto_id].push(reg);
    }

    return agrupado;
  }

  // ==================== OBTENER UNO ====================

  async findOne(id: string) {
    const registro = await this.prisma.producto_precio_cuota.findUnique({
      where: { id },
      include: {
        producto: {
          select: { id: true, descripcion: true, codigo_barra: true },
        },
      },
    });

    if (!registro) {
      throw new NotFoundException('Precio cuota no encontrado');
    }

    return registro;
  }

  // ==================== ACTUALIZAR ====================

  async update(id: string, dto: UpdateProductoPrecioCuotaDto, usuario?: string) {
    const registro = await this.prisma.producto_precio_cuota.findUnique({ where: { id } });

    if (!registro) {
      throw new NotFoundException('Precio cuota no encontrado');
    }

    // Recalcular monto_total si cambian cant_cuotas o monto_cuota
    const cantCuotas = dto.cant_cuotas ?? registro.cant_cuotas;
    const montoCuota = dto.monto_cuota ?? Number(registro.monto_cuota);
    const montoTotal = cantCuotas * montoCuota;

    const actualizado = await this.prisma.producto_precio_cuota.update({
      where: { id },
      data: {
        ...(dto.nombre !== undefined && { nombre: dto.nombre }),
        ...(dto.cant_cuotas !== undefined && { cant_cuotas: dto.cant_cuotas }),
        ...(dto.monto_cuota !== undefined && { monto_cuota: dto.monto_cuota }),
        monto_total: montoTotal,
        ...(dto.cuota_inicial !== undefined && { cuota_inicial: dto.cuota_inicial }),
        ...(dto.descuento_porcentaje !== undefined && { descuento_porcentaje: dto.descuento_porcentaje }),
        ...(dto.moneda !== undefined && { moneda: dto.moneda }),
        ...(dto.activo !== undefined && { activo: dto.activo }),
        ...(dto.orden !== undefined && { orden: dto.orden }),
        updated_at: new Date(),
        ...(usuario && { usuario }),
      },
    });

    this.logger.log(`Precio cuota actualizado: "${actualizado.nombre}" (${id})`, 'ProductoPrecioCuotasService');

    return actualizado;
  }

  // ==================== ELIMINAR ====================

  async remove(id: string) {
    const registro = await this.prisma.producto_precio_cuota.findUnique({ where: { id } });

    if (!registro) {
      throw new NotFoundException('Precio cuota no encontrado');
    }

    await this.prisma.producto_precio_cuota.delete({ where: { id } });

    this.logger.log(`Precio cuota eliminado: "${registro.nombre}" (${id})`, 'ProductoPrecioCuotasService');

    return { message: 'Precio cuota eliminado correctamente' };
  }

  // ==================== TOGGLE ACTIVO ====================

  async toggleActivo(id: string) {
    const registro = await this.prisma.producto_precio_cuota.findUnique({ where: { id } });

    if (!registro) {
      throw new NotFoundException('Precio cuota no encontrado');
    }

    const actualizado = await this.prisma.producto_precio_cuota.update({
      where: { id },
      data: { activo: !registro.activo, updated_at: new Date() },
    });

    this.logger.log(
      `Precio cuota ${actualizado.activo ? 'activado' : 'desactivado'}: "${actualizado.nombre}" (${id})`,
      'ProductoPrecioCuotasService',
    );

    return actualizado;
  }
}
