import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { HelpModel } from './entities/help.entity';
import { CreateHelpDto } from './dto/create-help.dto';
import { UpdateHelpDto } from './dto/update-help.dto';
import { FilterHelpDto } from './dto/filter-help.dto';

/**
 * Help Service
 *
 * @description
 * 도움말/툴팁 시스템 서비스입니다.
 * SNP, GENOME, MPT 등의 용어에 대한 도움말을 제공합니다.
 *
 * @export
 * @class HelpService
 */
@Injectable()
export class HelpService {
  constructor(
    @InjectRepository(HelpModel)
    private readonly helpRepository: Repository<HelpModel>,
  ) {}

  /**
   * 도움말 생성
   *
   * @param {CreateHelpDto} createHelpDto - 생성할 도움말 데이터
   * @param {string} userId - 생성자 ID
   * @param {string} ip - 생성자 IP
   * @returns {Promise<HelpModel>}
   */
  async create(createHelpDto: CreateHelpDto, userId: string, ip: string): Promise<HelpModel> {
    const help = this.helpRepository.create({
      ...createHelpDto,
      regUserId: userId,
      regIp: ip,
      useYn: createHelpDto.useYn || 'Y',
    });

    return await this.helpRepository.save(help);
  }

  /**
   * 전체 도움말 목록 조회
   *
   * @param {FilterHelpDto} filterDto - 필터 조건 (선택)
   * @returns {Promise<HelpModel[]>}
   */
  async findAll(filterDto?: FilterHelpDto): Promise<HelpModel[]> {
    const queryBuilder = this.helpRepository.createQueryBuilder('help');

    if (filterDto?.helpCtgry) {
      queryBuilder.andWhere('help.helpCtgry = :helpCtgry', { helpCtgry: filterDto.helpCtgry });
    }

    if (filterDto?.targetNm) {
      queryBuilder.andWhere('help.targetNm LIKE :targetNm', { targetNm: `%${filterDto.targetNm}%` });
    }

    if (filterDto?.useYn) {
      queryBuilder.andWhere('help.useYn = :useYn', { useYn: filterDto.useYn });
    }

    return await queryBuilder
      .orderBy('help.displayOrder', 'ASC')
      .addOrderBy('help.pkHelpNo', 'DESC')
      .getMany();
  }

  /**
   * 카테고리별 도움말 조회
   *
   * @param {string} category - 카테고리 (SNP/GENOME/MPT)
   * @returns {Promise<HelpModel[]>}
   */
  async findByCategory(category: string): Promise<HelpModel[]> {
    return await this.helpRepository.find({
      where: {
        helpCtgry: category,
        useYn: 'Y',
      },
      order: {
        displayOrder: 'ASC',
        pkHelpNo: 'DESC',
      },
    });
  }

  /**
   * 특정 대상명의 도움말 조회
   *
   * @param {string} category - 카테고리 (SNP/GENOME/MPT)
   * @param {string} targetNm - 대상명 (예: PLAG1, 도체중 등)
   * @returns {Promise<HelpModel>}
   */
  async findByTarget(category: string, targetNm: string): Promise<HelpModel> {
    const help = await this.helpRepository.findOne({
      where: {
        helpCtgry: category,
        targetNm: targetNm,
        useYn: 'Y',
      },
    });

    if (!help) {
      throw new NotFoundException(`도움말을 찾을 수 없습니다. (카테고리: ${category}, 대상: ${targetNm})`);
    }

    return help;
  }

  /**
   * 도움말 번호로 단건 조회
   *
   * @param {number} id - 도움말 번호
   * @returns {Promise<HelpModel>}
   */
  async findOne(id: number): Promise<HelpModel> {
    const help = await this.helpRepository.findOne({
      where: { pkHelpNo: id },
    });

    if (!help) {
      throw new NotFoundException(`도움말을 찾을 수 없습니다. (ID: ${id})`);
    }

    return help;
  }

  /**
   * 도움말 수정
   *
   * @param {number} id - 도움말 번호
   * @param {UpdateHelpDto} updateHelpDto - 수정할 데이터
   * @param {string} userId - 수정자 ID
   * @param {string} ip - 수정자 IP
   * @returns {Promise<HelpModel>}
   */
  async update(id: number, updateHelpDto: UpdateHelpDto, userId: string, ip: string): Promise<HelpModel> {
    const help = await this.findOne(id);

    Object.assign(help, updateHelpDto);
    help.updtUserId = userId;
    help.updtIp = ip;

    return await this.helpRepository.save(help);
  }

  /**
   * 도움말 삭제 (soft delete - useYn = 'N')
   *
   * @param {number} id - 도움말 번호
   * @param {string} userId - 삭제자 ID
   * @param {string} ip - 삭제자 IP
   * @returns {Promise<void>}
   */
  async remove(id: number, userId: string, ip: string): Promise<void> {
    const help = await this.findOne(id);

    help.useYn = 'N';
    help.updtUserId = userId;
    help.updtIp = ip;

    await this.helpRepository.save(help);
  }

  /**
   * 도움말 영구 삭제 (hard delete)
   *
   * @param {number} id - 도움말 번호
   * @returns {Promise<void>}
   */
  async hardRemove(id: number): Promise<void> {
    const help = await this.findOne(id);
    await this.helpRepository.remove(help);
  }
}
