import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Repository } from 'typeorm';
import { GeneDetailModel } from './entities/gene-detail.entity';
import { GenomeRequestModel } from '../genome/entities/genome-request.entity';

@Injectable()
export class GeneService {
  constructor(
    @InjectRepository(GeneDetailModel)
    private readonly geneDetailRepository: Repository<GeneDetailModel>,
    @InjectRepository(GenomeRequestModel)
    private readonly genomeRequestRepository: Repository<GenomeRequestModel>,
  ) {}

  /**
   * 개체식별번호(cowId)로 유전자 상세 정보 조회
   * @param cowId 개체식별번호 (KOR...)
   * @returns 유전자 상세 정보 배열
   */
  async findByCowId(cowId: string): Promise<GeneDetailModel[]> {
    const results = await this.geneDetailRepository.find({
      where: {
        cowId,
        delDt: IsNull(),
      },
      relations: ['genomeRequest'],
      order: {
        chromosome: 'ASC',
        position: 'ASC',
      },
    });

    return results;
  }

  /**
   * 의뢰번호(requestNo)로 유전자 상세 정보 조회
   * @param requestNo 의뢰번호
   * @returns 유전자 상세 정보 배열
   */
  async findByRequestNo(requestNo: number): Promise<GeneDetailModel[]> {
    const results = await this.geneDetailRepository.find({
      where: {
        fkRequestNo: requestNo,
        delDt: IsNull(),
      },
      order: {
        chromosome: 'ASC',
        position: 'ASC',
      },
    });

    return results;
  }

  /**
   * 개체별 유전자 요약 정보 조회
   * @param cowId 개체식별번호
   * @returns 동형접합/이형접합 개수 요약
   */
  async getGeneSummary(cowId: string): Promise<{
    total: number;
    homozygousCount: number;
    heterozygousCount: number;
  }> {
    const geneDetails = await this.findByCowId(cowId);

    let homozygousCount = 0;
    let heterozygousCount = 0;

    geneDetails.forEach((gene) => {
      if (gene.allele1 && gene.allele2) {
        if (gene.allele1 === gene.allele2) {
          homozygousCount++;
        } else {
          heterozygousCount++;
        }
      }
    });

    return {
      total: geneDetails.length,
      homozygousCount,
      heterozygousCount,
    };
  }

  /**
   * 유전자 상세 정보 단건 조회
   * @param geneDetailNo 유전자상세번호
   * @returns 유전자 상세 정보
   */
  async findOne(geneDetailNo: number): Promise<GeneDetailModel> {
    const result = await this.geneDetailRepository.findOne({
      where: {
        pkGeneDetailNo: geneDetailNo,
        delDt: IsNull(),
      },
      relations: ['genomeRequest'],
    });

    if (!result) {
      throw new NotFoundException(`유전자 상세 정보를 찾을 수 없습니다. (geneDetailNo: ${geneDetailNo})`);
    }

    return result;
  }

  /**
   * 유전자 상세 정보 생성
   * @param data 생성할 데이터
   * @returns 생성된 유전자 상세 정보
   */
  async create(data: Partial<GeneDetailModel>): Promise<GeneDetailModel> {
    const geneDetail = this.geneDetailRepository.create(data);
    return await this.geneDetailRepository.save(geneDetail);
  }

  /**
   * 유전자 상세 정보 일괄 생성
   * @param dataList 생성할 데이터 배열
   * @returns 생성된 유전자 상세 정보 배열
   */
  async createBulk(dataList: Partial<GeneDetailModel>[]): Promise<GeneDetailModel[]> {
    const geneDetails = this.geneDetailRepository.create(dataList);
    return await this.geneDetailRepository.save(geneDetails);
  }
}
