import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository, IsNull } from 'typeorm';
import { MptModel } from './entities/mpt.entity';
import {
  MPT_REFERENCE_RANGES,
  MPT_CATEGORIES,
  MptReferenceRange,
  MptCategory,
} from '../common/const/MptReference';
import { MptStatisticsDto } from './dto/mpt-statistics.dto';

@Injectable()
export class MptService {
  constructor(
    @InjectRepository(MptModel)
    private readonly mptRepository: Repository<MptModel>,
  ) {}

  async findByCowShortNo(cowShortNo: string): Promise<MptModel[]> {
    return this.mptRepository.find({
      where: { cowShortNo: cowShortNo, delDt: IsNull() },
      relations: ['cow', 'cow.farm'],
      order: { testDt: 'DESC' },
    });
  }

  async findByCowId(cowId: string): Promise<MptModel[]> {
    return this.mptRepository.find({
      where: { cowId: cowId, delDt: IsNull() },
      relations: ['cow', 'cow.farm'],
      order: { testDt: 'DESC' },
    });
  }

  /**
   * 농장별 MPT 통계 조회
   * - 개체별 최신 검사 결과 기준
   * - 카테고리별 정상/주의/위험 개체 수
   * - 위험 개체 목록 (Top 5)
   */
  async getMptStatistics(farmNo: number): Promise<MptStatisticsDto> {
    // 농장의 모든 MPT 데이터 조회
    const allMptData = await this.mptRepository.find({
      where: { fkFarmNo: farmNo, delDt: IsNull() },
      order: { testDt: 'DESC' },
    });

    if (allMptData.length === 0) {
      return {
        totalMptCows: 0,
        latestTestDate: null,
        categories: {
          energy: { safe: 0, caution: 0 },
          protein: { safe: 0, caution: 0 },
          liver: { safe: 0, caution: 0 },
          mineral: { safe: 0, caution: 0 },
        },
        riskyCows: [],
      };
    }

    // 개체별 최신 검사 데이터만 추출
    const latestByCoW = new Map<string, MptModel>();
    for (const mpt of allMptData) {
      if (!mpt.cowId) continue;
      if (!latestByCoW.has(mpt.cowId)) {
        latestByCoW.set(mpt.cowId, mpt);
      }
    }

    const latestMptData = Array.from(latestByCoW.values());
    const totalMptCows = latestMptData.length;
    const latestTestDate = latestMptData[0]?.testDt || null;

    // 카테고리별 통계 초기화 (안전/주의 2단계)
    const categoryStats = {
      energy: { safe: 0, caution: 0 },
      protein: { safe: 0, caution: 0 },
      liver: { safe: 0, caution: 0 },
      mineral: { safe: 0, caution: 0 },
    };

    // 주의 개체 목록
    const riskyCowsList: MptStatisticsDto['riskyCows'] = [];

    // 각 개체별로 카테고리별 상태 평가
    for (const mpt of latestMptData) {
      // 각 카테고리별로 이상 항목이 있는지 체크 (안전/주의 2단계)
      const categoryStatus: Record<string, 'safe' | 'caution'> = {
        energy: 'safe',
        protein: 'safe',
        liver: 'safe',
        mineral: 'safe',
      };

      // 각 항목별 체크 (범위 내 = 안전, 범위 밖 = 주의)
      const checkItem = (value: number | null, itemKey: string) => {
        if (value === null || value === undefined) return;
        const ref = MPT_REFERENCE_RANGES[itemKey];
        if (!ref) return;

        const category = ref.category as keyof typeof categoryStatus;

        // 범위 밖이면 주의
        if (value > ref.upperLimit || value < ref.lowerLimit) {
          categoryStatus[category] = 'caution';

          // 주의 개체 목록에 추가
          riskyCowsList.push({
            cowId: mpt.cowId,
            category,
            itemName: itemKey,
            value,
            status: value > ref.upperLimit ? 'high' : 'low',
          });
        }
      };

      // 에너지 카테고리
      checkItem(mpt.glucose, 'glucose');
      checkItem(mpt.cholesterol, 'cholesterol');
      checkItem(mpt.nefa, 'nefa');
      checkItem(mpt.bcs, 'bcs');

      // 단백질 카테고리
      checkItem(mpt.totalProtein, 'totalProtein');
      checkItem(mpt.albumin, 'albumin');
      checkItem(mpt.globulin, 'globulin');
      checkItem(mpt.agRatio, 'agRatio');
      checkItem(mpt.bun, 'bun');

      // 간기능 카테고리
      checkItem(mpt.ast, 'ast');
      checkItem(mpt.ggt, 'ggt');
      checkItem(mpt.fattyLiverIdx, 'fattyLiverIdx');

      // 미네랄 카테고리
      checkItem(mpt.calcium, 'calcium');
      checkItem(mpt.phosphorus, 'phosphorus');
      checkItem(mpt.caPRatio, 'caPRatio');
      checkItem(mpt.magnesium, 'magnesium');

      // 카테고리별 통계 업데이트
      for (const [cat, status] of Object.entries(categoryStatus)) {
        const category = cat as keyof typeof categoryStats;
        categoryStats[category][status]++;
      }
    }

    // 위험 개체 정렬 및 상위 5개만
    const sortedRiskyCows = riskyCowsList
      .sort((a, b) => {
        // 범위 이탈 정도로 정렬
        const refA = MPT_REFERENCE_RANGES[a.itemName];
        const refB = MPT_REFERENCE_RANGES[b.itemName];
        const deviationA = a.status === 'high'
          ? (a.value - refA.upperLimit) / (refA.upperLimit - refA.lowerLimit)
          : (refA.lowerLimit - a.value) / (refA.upperLimit - refA.lowerLimit);
        const deviationB = b.status === 'high'
          ? (b.value - refB.upperLimit) / (refB.upperLimit - refB.lowerLimit)
          : (refB.lowerLimit - b.value) / (refB.upperLimit - refB.lowerLimit);
        return deviationB - deviationA;
      })
      .slice(0, 5);

    return {
      totalMptCows,
      latestTestDate,
      categories: categoryStats,
      riskyCows: sortedRiskyCows,
    };
  }

  /**
   * MPT 참조값 조회
   */
  getReferenceValues(): { references: Record<string, MptReferenceRange>; categories: MptCategory[] } {
    return {
      references: MPT_REFERENCE_RANGES,
      categories: MPT_CATEGORIES,
    };
  }
}
