import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { UsersEntity } from 'src/entities/Users.entity';
import { UpdateUserDto } from './dto/update-user.dto';
import { CreateUserDto } from './dto/create-user.dto';
import {
  getSkipOffset,
  paginate,
} from 'src/config/pagination/pagination.service';
import { Response } from 'src/config/pagination/paginationDto';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(UsersEntity)
    private usersRepository: Repository<UsersEntity>,
  ) {}

  async getUserCounts() {
    const result = await this.usersRepository
      .createQueryBuilder('user')
      .select('COUNT(*)', 'total')
      .addSelect(
        `SUM(CASE WHEN user.status = 'active' THEN 1 ELSE 0 END)`,
        'active',
      )
      .addSelect(
        `SUM(CASE WHEN user.status = 'inactive' THEN 1 ELSE 0 END)`,
        'inactive',
      )
      .getRawOne();

    return {
      total: Number(result.total),
      active: Number(result.active),
      inactive: Number(result.inactive),
    };
  }

  async create(createUserDto: any): Promise<any> {
    if (createUserDto.exit_date === '') createUserDto.exit_date = null;
    const user = this.usersRepository.create(createUserDto);
    return await this.usersRepository.save(user);
  }

  // async findAll(): Promise<UsersEntity[]> {
  //   return await this.usersRepository.find();
  // }

  // async findAll(searchDto: any): Promise<Response<UsersEntity>> {
  //   const query = this.usersRepository
  //     .createQueryBuilder('user')
  //     // .leftJoinAndSelect('user.deviceAssignments', 'assignments')
  //     .leftJoinAndSelect(
  //       'user.deviceAssignments2',
  //       'assignment',
  //       `assignment.id = (
  //         SELECT da.id
  //         FROM device_assignments da
  //         WHERE da.employee_id = user.id
  //         ORDER BY da.assigned_date DESC, da.id DESC
  //         LIMIT 1
  //       )`,
  //     )

  //     // optional: join device
  //     .leftJoinAndSelect('assignment.device', 'device')
  //     .orderBy('user.id', 'DESC');

  //   if (searchDto.search_title) {
  //     query.andWhere(
  //       `(user.first_name LIKE :search OR user.last_name LIKE :search OR user.email LIKE :search OR user.employee_code LIKE :search OR user.department LIKE :search OR user.designation LIKE :search)`,
  //       {
  //         search: `%${searchDto.search_title}%`,
  //       },
  //     );
  //   }

  //   /**
  //    * Filter by creators
  //    */
  //   if (searchDto.created_by && searchDto.created_by.length > 0) {
  //     query.andWhere('user.created_by IN (:...created_by)', {
  //       created_by: searchDto.created_by,
  //     });
  //   }

  //   /**
  //    * Filter by updaters
  //    */
  //   if (searchDto.updated_by && searchDto.updated_by.length > 0) {
  //     query.andWhere('user.modified_by IN (:...updated_by)', {
  //       updated_by: searchDto.updated_by,
  //     });
  //   }

  //   /**
  //    * Filter by active status
  //    */
  //   if (searchDto.status && searchDto.status.length > 0) {
  //     query.andWhere('user.status IN (:...status)', {
  //       status: searchDto.status,
  //     });
  //   }

  //   /**
  //    * Created Date Range
  //    */
  //   if (searchDto.join_date) {
  //     const { from, to } = searchDto.join_date;

  //     if (from && to) {
  //       query.andWhere('user.join_date BETWEEN :createdFrom AND :createdTo', {
  //         createdFrom: from,
  //         createdTo: to,
  //       });
  //     } else if (from) {
  //       query.andWhere('user.join_date >= :createdFrom', {
  //         createdFrom: from,
  //       });
  //     } else if (to) {
  //       query.andWhere('user.join_date <= :createdTo', {
  //         createdTo: to,
  //       });
  //     }
  //   }
  //   if (searchDto.created_on) {
  //     const { from, to } = searchDto.created_on;

  //     if (from && to) {
  //       query.andWhere('user.created_at BETWEEN :createdFrom AND :createdTo', {
  //         createdFrom: from,
  //         createdTo: to,
  //       });
  //     } else if (from) {
  //       query.andWhere('user.created_at >= :createdFrom', {
  //         createdFrom: from,
  //       });
  //     } else if (to) {
  //       query.andWhere('user.created_at <= :createdTo', {
  //         createdTo: to,
  //       });
  //     }
  //   }

  //   /**
  //    * Updated Date Range
  //    */
  //   if (searchDto.updated_on) {
  //     const { from, to } = searchDto.updated_on;

  //     if (from && to) {
  //       query.andWhere('user.updated_at BETWEEN :updatedFrom AND :updatedTo', {
  //         updatedFrom: from,
  //         updatedTo: to,
  //       });
  //     } else if (from) {
  //       query.andWhere('user.updated_at >= :updatedFrom', {
  //         updatedFrom: from,
  //       });
  //     } else if (to) {
  //       query.andWhere('user.updated_at <= :updatedTo', {
  //         updatedTo: to,
  //       });
  //     }
  //   }

  //   /**
  //    * Pagination
  //    */
  //   const [skip, limit] = getSkipOffset(searchDto);
  //   const [data, total] = await query.skip(skip).take(limit).getManyAndCount();

  //   const pagination = paginate(total, searchDto.per_page, searchDto.page);

  //   return {
  //     list: data,
  //     pagination,
  //   };
  // }

  async findAll(searchDto: any): Promise<Response<any>> {
    const query = this.usersRepository
      .createQueryBuilder('user')

      .select([
        'user.id',
        'user.employee_code',
        'user.first_name',
        'user.last_name',
        'user.email',
        'user.department',
        'user.designation',
        'user.status',
      ])

      // ✅ Latest assignment
      .leftJoinAndMapOne(
        'user.latest_assignment',
        'device_assignments',
        'assignment',
        `assignment.id = (
      SELECT da.id
      FROM device_assignments da
      WHERE da.employee_id = user.id
      ORDER BY 
        da.assigned_date IS NULL,
        da.assigned_date DESC,
        da.id DESC
      LIMIT 1
    )`,
      )

      // ✅ FIXED device join
      .leftJoinAndMapOne(
        'user.latest_assignment.device',
        'devices',
        'device',
        'device.id = assignment.device_id',
      )

      .orderBy('user.id', 'DESC');

    /** 🔍 Search */
    if (searchDto.search_title) {
      query.andWhere(
        `(user.first_name LIKE :search 
          OR user.last_name LIKE :search 
          OR user.email LIKE :search 
          OR user.employee_code LIKE :search 
          OR user.department LIKE :search 
          OR user.designation LIKE :search)`,
        {
          search: `%${searchDto.search_title}%`,
        },
      );
    }

    /** 🔍 Status filter */
    if (searchDto.status?.length) {
      query.andWhere('user.status IN (:...status)', {
        status: searchDto.status,
      });
    }

    /** 📅 Join Date filter */
    if (searchDto.join_date) {
      const { from, to } = searchDto.join_date;

      if (from && to) {
        query.andWhere('user.join_date BETWEEN :from AND :to', { from, to });
      } else if (from) {
        query.andWhere('user.join_date >= :from', { from });
      } else if (to) {
        query.andWhere('user.join_date <= :to', { to });
      }
    }

    /** 📅 Created Date filter */
    if (searchDto.created_on) {
      const { from, to } = searchDto.created_on;

      if (from && to) {
        query.andWhere('user.created_at BETWEEN :from AND :to', {
          from,
          to,
        });
      } else if (from) {
        query.andWhere('user.created_at >= :from', { from });
      } else if (to) {
        query.andWhere('user.created_at <= :to', { to });
      }
    }

    /** 📅 Updated Date filter */
    if (searchDto.updated_on) {
      const { from, to } = searchDto.updated_on;

      if (from && to) {
        query.andWhere('user.updated_at BETWEEN :from AND :to', {
          from,
          to,
        });
      } else if (from) {
        query.andWhere('user.updated_at >= :from', { from });
      } else if (to) {
        query.andWhere('user.updated_at <= :to', { to });
      }
    }

    /** 📦 Pagination */
    const [skip, limit] = getSkipOffset(searchDto);

    const [data, total] = await query.skip(skip).take(limit).getManyAndCount();

    const pagination = paginate(total, searchDto.per_page, searchDto.page);
    
    // ✅ Transform response (FIXED mapping)
    const formatted = data.map((user: any) => {
      const latest = user.latest_assignment || null;
      return {
        id: user.id,
        employee_code: user.employee_code,
        first_name: user.first_name,
        email: user.email,

        latest_assignment: latest
          ? latest
          : null,
      };
    });

    return {
      list: formatted,
      pagination,
    };
  }

  async findOne(id: string): Promise<any> {
    const user = await this.usersRepository.findOne({
      where: { id: id as any },
    });
    if (!user) {
      throw new NotFoundException(`User with ID ${id} not found`);
    }
    return user;
  }

  async findByEmail(email: string): Promise<any> {
    const user = await this.usersRepository.findOne({
      where: { email: email as any },
    });
    if (!user) {
      throw new NotFoundException(`User with ID ${email} not found`);
    }
    return user;
  }

  // async update(id: string, updateUserDto: any): Promise<any> {
  //   const user = await this.findOne(id);
  //   this.usersRepository.merge(user, updateUserDto);
  //   return await this.usersRepository.save(user);
  // }

  async edit(id: string, updateUserDto: any): Promise<any> {
    const user = await this.findOne(id);
    this.usersRepository.merge(user, updateUserDto);
    return await this.usersRepository.save(user);
  }

  // async remove(id: string): Promise<void> {
  //   const user = await this.findOne(id);
  //   await this.usersRepository.remove(user);
  // }

  async findOneByAppleId(appleId: string): Promise<any> {
    // return await this.usersRepository.findOne({ where: { appleId } });
  }

  async findOneByGoogleId(googleId: string): Promise<any> {
    // return await this.usersRepository.findOne({ where: { googleId } });
  }

  async updateStatus(userId: string, updateStatusDto: any) {
    const { ids, action } = updateStatusDto;

    // Execute bulk update query
    return await this.usersRepository
      .createQueryBuilder()
      .update()
      .set({
        status: action === 'activate' ? 'active' : 'inactive', // Status mapping
        // modified_by_user: Number(userId), // Track updater
      })
      .where('id IN (:...ids)', { ids })
      .execute();
  }
}
// @Injectable()
// export class UsersService {
//   constructor(@InjectRepository(User) private repo: Repository<User>) {}

//   create(dto: CreateUserDto) {
//     return this.repo.save(this.repo.create(dto));
//   }

//   findAll() {
//     return this.repo.find({ relations: ['manager'] });
//   }

//   findOne(id: number) {
//     return this.repo.findOne({ where: { id } });
//   }

//   async update(id: number, dto: UpdateUserDto) {
//     await this.repo.update(id, dto);
//     return this.findOne(id);
//   }

//   remove(id: number) {
//     return this.repo.delete(id);
//   }
// }
