// Import NestJS decorators and utilities
import { Inject, Injectable } from '@nestjs/common';

// Import TypeORM decorators for dependency injection
import { InjectRepository } from '@nestjs/typeorm';

// Import TypeORM core classes
import { DataSource, Repository } from 'typeorm';

// Import entity definitions
import { UserSettingsEntity } from 'src/entities/UserSettings.entity';

// Import DTOs for request validation
import { CreateUserSettingsDto } from './dto/create.dto';

// Import class-transformer for object transformation
import { plainToInstance } from 'class-transformer';

// Import pagination utilities
import {
  getSkipOffset,
  paginate,
} from 'src/config/pagination/pagination.service';
import { SearchUserSettingsDto } from './dto/search-dto';
import { UpdateUserSettingsDto } from './dto/update.dto';
import { Response } from 'src/config/pagination/paginationDto';

// Import cache-related dependencies
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';

// Import additional entity for table settings
import { LmsTableSettingsEntity } from 'src/entities/LmsTableSettings.entity';

/**
 * UserSettingsService - Service layer for user settings management
 *
 * This service handles CRUD operations for user-specific settings and preferences.
 * It provides basic data access functionality with minimal business logic,
 * focusing on straightforward entity management.
 *
 * Business Domain: User Configuration Management
 * - Manages user-specific application settings
 * - Handles basic CRUD operations for settings
 * - Integrates with table settings for extended functionality
 *
 * Key Characteristics:
 * - Simple CRUD operations with minimal complexity
 * - Basic pagination and filtering
 * - Integration with table settings entity
 * - Cache manager injected but not utilized (potential for optimization)
 *
 * Note: This service appears to be a basic data access layer with room
 * for enhanced functionality like caching, validation, and business logic.
 */
@Injectable()
export class UserSettingsService {
  /**
   * Constructor with dependency injection
   *
   * @param datasource - TypeORM DataSource (injected but not used in current implementation)
   * @param cacheManager - Cache manager (injected but not used - opportunity for optimization)
   * @param groupRepo - Repository for UserSettingsEntity (note: 'group' naming might be legacy)
   * @param tableSettingRepo - Repository for LmsTableSettingsEntity
   */
  constructor(
    private datasource: DataSource,
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
    @InjectRepository(UserSettingsEntity)
    private readonly groupRepo: Repository<UserSettingsEntity>,
    @InjectRepository(LmsTableSettingsEntity)
    private readonly tableSettingRepo: Repository<LmsTableSettingsEntity>,
  ) {}

  /**
   * findAll - Retrieves paginated user settings with basic filtering
   *
   * This implementation provides basic pagination but lacks advanced filtering
   * capabilities that are typically expected from a search endpoint.
   * The SearchUserSettingsDto is accepted but not utilized for filtering.
   *
   * @param searchDto - Search parameters (currently not used for filtering)
   * @returns Paginated response with user settings
   *
   * Improvement Opportunity:
   * - Implement actual filtering based on searchDto parameters
   * - Add caching for frequently accessed settings lists
   * - Add sorting options beyond default ID ordering
   */
  async findAll(
    searchDto: SearchUserSettingsDto,
  ): Promise<Response<UserSettingsEntity>> {
    const query = this.groupRepo
      .createQueryBuilder('setting')
      .leftJoin('setting.user', 'user')
      .addSelect(['user.fname', 'user.lname', 'user.employeeCode'])
      .orderBy('setting.id', 'DESC');

    // Note: No filtering logic implemented despite having searchDto
    // Potential filters could be added based on searchDto properties

    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 };
  }

  /**
   * findOne - Retrieves a single user setting by ID
   *
   * Basic retrieval with user relation eager loading.
   * No caching implemented despite having cacheManager available.
   *
   * @param id - User setting ID
   * @returns User setting entity with related user information
   *
   * Improvement Opportunity:
   * - Implement caching with cache-aside pattern
   * - Add error handling for non-existent IDs
   * - Consider returning specific DTO instead of full entity
   */
  findOne(id: number) {
    return this.groupRepo.findOne({ where: { id }, relations: ['user'] });
  }

  /**
   * create - Creates a new user setting
   *
   * Basic creation with user tracking (by_user field).
   * Uses DTO transformation for data consistency.
   *
   * @param userId - ID of the user creating the setting
   * @param createDto - Validated creation data
   * @returns Created user setting entity
   *
   * Improvement Opportunity:
   * - Add validation for duplicate settings
   * - Implement transaction if creating related entities
   * - Add audit logging for setting creation
   */
  create(userId: number, createDto: CreateUserSettingsDto) {
    const userSettingsEntity = plainToInstance(UserSettingsEntity, {
      ...createDto,
      by_user: userId, // Track creator
    });
    return this.groupRepo.save(userSettingsEntity);
  }

  /**
   * update - Updates an existing user setting
   *
   * Simple update operation without validation or business logic.
   *
   * @param id - User setting ID to update
   * @param updateDto - Validated update data
   * @returns Update result
   *
   * Improvement Opportunity:
   * - Validate that the setting exists before updating
   * - Check if user has permission to update this setting
   * - Implement optimistic locking to prevent conflicts
   * - Add audit trail for updates
   */
  update(id: number, updateDto: UpdateUserSettingsDto) {
    const userSettingsEntity = plainToInstance(UserSettingsEntity, {
      ...updateDto,
    });
    return this.groupRepo.update(id, userSettingsEntity);
  }

  /**
   * delete - Deletes a user setting
   *
   * Simple delete operation without validation or cascade handling.
   *
   * @param id - User setting ID to delete
   * @returns Delete result
   *
   * Improvement Opportunity:
   * - Validate existence before deletion
   * - Check permissions before deletion
   * - Handle cascade deletion of related entities if needed
   * - Implement soft delete instead of hard delete
   */
  delete(id: number) {
    return this.groupRepo.delete(id);
  }

  /**
   * findTableSettings - Retrieves table settings for a user
   *
   * Simple lookup method for table settings.
   * Used by other services but could be enhanced.
   *
   * @param userId - User ID
   * @param setting - Setting type identifier
   * @returns Table settings entity or null
   *
   * Improvement Opportunity:
   * - Implement caching for frequently accessed table settings
   * - Add default settings generation if not found
   * - Consider moving to TableSettingsService for consistency
   */
  findTableSettings(userId: number, setting: string) {
    return this.tableSettingRepo.findOne({
      where: { user_id: userId, setting_type: setting },
    });
  }
}
