import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Movimiento } from './entities/movimiento.entity';
import { Usuario } from 'src/usuarios/entities/usuario.entity';
import { Equipo } from 'src/equipo/entities/equipo.entity';
import { CreateMovimientoDto } from './dto/create-movimiento.dto';

@Injectable()
export class MovimientoService {
  constructor(
    @InjectRepository(Movimiento)
    private readonly movimientoRepo: Repository<Movimiento>,
  ) {}

  async crear(dto: CreateMovimientoDto) {
    const movimiento = this.movimientoRepo.create({
      user: { id_usuario: dto.idUsuario },
      equipo: { id_equipo: dto.idEquipo },
      fechaMovimiento: new Date(),
      observaciones: dto.observaciones,
    });

    return await this.movimientoRepo.save(movimiento);
  }

  async buscar(idEquipo: number) {
    const movimiento = await this.movimientoRepo.findOne({
      where: { equipo: { id_equipo: idEquipo } },
      order: { fechaMovimiento: 'DESC' },
      relations: ['user'],
    });

    return movimiento;
  }

  async searchByIdUser(id_usuario: number) {
    const movimientos = await this.movimientoRepo
      .createQueryBuilder('mov')
      .leftJoinAndSelect('mov.equipo', 'equipo')
      .leftJoinAndSelect('equipo.tipoEquipo', 'tipoEquipo')
      .leftJoinAndSelect('equipo.periferico', 'periferico')
      .leftJoin('mov.user', 'user')
      .where('user.id_usuario = :id_usuario', { id_usuario })
      .orderBy('mov.fechaMovimiento', 'DESC')
      .getMany();

    if (!movimientos.length) {
      throw new NotFoundException('Sin equipos modificados o guardados');
    }

    const vistos = new Set<string>();
    const unicos: Movimiento[] = [];

    for (const mov of movimientos) {
      const inventario = mov.equipo?.inventario;

      if (!vistos.has(inventario)) {
        vistos.add(inventario);
        unicos.push(mov);
      }
    }

    return unicos.map((mov) => ({
      inventario: mov.equipo?.inventario,
      tipo_equipo: mov.equipo?.tipoEquipo?.tipo_equipo,
      periferico: mov.equipo?.periferico?.periferico,
      fechaMovimiento: mov.fechaMovimiento,
      lugar: mov.equipo?.lugar,
      observaciones: mov.observaciones,
    }));
  }

  async countCensosPorDiaUnicos() {
    const result = await this.movimientoRepo
      .createQueryBuilder('mov')
      .innerJoin('mov.equipo', 'equipo')
      .select('DATE(mov.fechaMovimiento)', 'fecha')
      .addSelect('COUNT(DISTINCT equipo.inventario)', 'total')
      .groupBy('DATE(mov.fechaMovimiento)')
      .orderBy('fecha', 'DESC')
      .getRawMany();

    return result.map((r) => ({
      fecha: r.fecha,
      total: Number(r.total),
    }));
  }
}
