package kr.co.jinwoosi.clfd.clfd.dgns.service;

import kr.co.jinwoosi.clfd.clfd.dgns.mapper.DgnsMapper;
import kr.co.jinwoosi.clfd.clfd.dgns.model.*;
import kr.co.jinwoosi.clfd.clfd.dgns.vo.DgnsSelection;
import kr.co.jinwoosi.clfd.framework.security.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DgnsService {

    @Autowired
    private DgnsMapper dgnsMapper;
    @Autowired
    private DgnsAskService dgnsAskService;
    @Autowired
    private DgnsDtlService dgnsDtlService;
    @Autowired
    private SkTyService skTyService;

    public List<Dgns> selectList(DgnsSearch dgnsSearch) {
        List<Dgns> dgnsList = dgnsMapper.selectList(dgnsSearch);
        List<DgnsDtl> dgnsDtlList = dgnsDtlService.getCashedDgnsDtlList(false);
        List<SkTy> skTyList = skTyService.getCashedSkTyList(false);
        for (Dgns dgns : dgnsList) {
            // 진단 상세 저장
            for (DgnsDtl dgnsDtl : dgnsDtlList) {
                Long dgnsDtlId = dgnsDtl.getDgnsDtlId();
                if (dgnsDtlId.equals(dgns.getOdDgnsDtlId())) {
                    dgns.setOdDgnsDtl(dgnsDtl);
                } else if (dgnsDtlId.equals(dgns.getSrDgnsDtlId())) {
                    dgns.setSrDgnsDtl(dgnsDtl);
                } else if (dgnsDtlId.equals(dgns.getPnDgnsDtlId())) {
                    dgns.setPnDgnsDtl(dgnsDtl);
                } else if (dgnsDtlId.equals(dgns.getWtDgnsDtlId())) {
                    dgns.setWtDgnsDtl(dgnsDtl);
                }
            }
            // 피부타입 저장
            for (SkTy skTy : skTyList) {
                if (dgns.getSkTyId().equals(skTy.getSkTyId())) {
                    dgns.setSkTy(skTy);
                    break;
                }
            }
        }
        return dgnsList;
    }

    public Dgns select(DgnsSearch dgnsSearch) {
        Dgns dgns = dgnsMapper.select(dgnsSearch);
        if (dgns==null) {
            return null;
        }
        // 피부타입 저장
        SkTySearch skTySearch = new SkTySearch();
        skTySearch.setSkTyId(dgns.getSkTyId());
        SkTy skTy = skTyService.select(skTySearch);
        dgns.setSkTy(skTy);
        // 진단상세 저장
        List<DgnsDtl> dgnsDtlList = dgnsDtlService.getCashedDgnsDtlList(false);
        dgns.setOdDgnsDtl(findDgnsDtlById(dgnsDtlList, dgns.getOdDgnsDtlId()));
        dgns.setSrDgnsDtl(findDgnsDtlById(dgnsDtlList, dgns.getSrDgnsDtlId()));
        dgns.setPnDgnsDtl(findDgnsDtlById(dgnsDtlList, dgns.getPnDgnsDtlId()));
        dgns.setWtDgnsDtl(findDgnsDtlById(dgnsDtlList, dgns.getWtDgnsDtlId()));
        return dgns;
    }

    // 진단 결과를 저장
    public void saveDgns(Long userId, Dgns dgns) {
        dgns.setUserId(userId);
        dgns.setRegId(userId);
        DgnsSearch dgnsCountSearch = new DgnsSearch();
        dgnsCountSearch.setUserId(userId);
        dgnsCountSearch.setRecSt("Y");
        dgns.setDgnsCnt(dgnsMapper.count(dgnsCountSearch) + 1); // 진단회차 저장
        dgnsMapper.insert(dgns);
    }

    public Dgns examDgns(List<DgnsSelection> dgnsSelectionList) {
        Dgns dgns = new Dgns();
        List<DgnsAsk> dgnsAskList = dgnsAskService.getCashedDgnsAskList(false);
        List<DgnsDtl> dgnsDtlList = dgnsDtlService.getCashedDgnsDtlList(false);
        dgns.setOdTotalScore(calculateDgnsTotalScore("OD", dgnsAskList, dgnsSelectionList));
        dgns.setSrTotalScore(calculateDgnsTotalScore("SR", dgnsAskList, dgnsSelectionList));
        dgns.setPnTotalScore(calculateDgnsTotalScore("PN", dgnsAskList, dgnsSelectionList));
        dgns.setWtTotalScore(calculateDgnsTotalScore("WT", dgnsAskList, dgnsSelectionList));
        dgns.setOdDgnsDtl(findDgnsDtlByScore("OD", dgnsDtlList, dgns.getOdTotalScore()));
        dgns.setSrDgnsDtl(findDgnsDtlByScore("SR", dgnsDtlList, dgns.getSrTotalScore()));
        dgns.setPnDgnsDtl(findDgnsDtlByScore("PN", dgnsDtlList, dgns.getPnTotalScore()));
        dgns.setWtDgnsDtl(findDgnsDtlByScore("WT", dgnsDtlList, dgns.getWtTotalScore()));
        dgns.setOdDgnsDtlId(dgns.getOdDgnsDtl().getDgnsDtlId());
        dgns.setSrDgnsDtlId(dgns.getSrDgnsDtl().getDgnsDtlId());
        dgns.setPnDgnsDtlId(dgns.getPnDgnsDtl().getDgnsDtlId());
        dgns.setWtDgnsDtlId(dgns.getWtDgnsDtl().getDgnsDtlId());
        dgns.setSkTy(skTyService.selectSkTyByDgnsDtlList(dgns.getDgnsDtlList()));
        dgns.setSkTyId(dgns.getSkTy().getSkTyId());
        return dgns;
    }

    public Dgns examDgnsByScore(String odScore, String srScore, String pnScore, String wtScore) {
        Dgns dgns = new Dgns();
        List<DgnsDtl> dgnsDtlList = dgnsDtlService.getCashedDgnsDtlList(false);
        dgns.setOdTotalScore(Double.parseDouble(odScore));
        dgns.setSrTotalScore(Double.parseDouble(srScore));
        dgns.setPnTotalScore(Double.parseDouble(pnScore));
        dgns.setWtTotalScore(Double.parseDouble(wtScore));
        dgns.setOdDgnsDtl(findDgnsDtlByScore("OD", dgnsDtlList, dgns.getOdTotalScore()));
        dgns.setSrDgnsDtl(findDgnsDtlByScore("SR", dgnsDtlList, dgns.getSrTotalScore()));
        dgns.setPnDgnsDtl(findDgnsDtlByScore("PN", dgnsDtlList, dgns.getPnTotalScore()));
        dgns.setWtDgnsDtl(findDgnsDtlByScore("WT", dgnsDtlList, dgns.getWtTotalScore()));
        dgns.setOdDgnsDtlId(dgns.getOdDgnsDtl().getDgnsDtlId());
        dgns.setSrDgnsDtlId(dgns.getSrDgnsDtl().getDgnsDtlId());
        dgns.setPnDgnsDtlId(dgns.getPnDgnsDtl().getDgnsDtlId());
        dgns.setWtDgnsDtlId(dgns.getWtDgnsDtl().getDgnsDtlId());
        dgns.setSkTy(skTyService.selectSkTyByDgnsDtlList(dgns.getDgnsDtlList()));
        dgns.setSkTyId(dgns.getSkTy().getSkTyId());
        return dgns;
    }

    public Double calculateDgnsTotalScore(String dgnsTyCd, List<DgnsAsk> dgnsAskList, List<DgnsSelection> dgnsSelectionList) {
        Double totalScore = 0.0;
        List<DgnsAsk> filteredDgnsAskList = dgnsAskList.stream().filter(dgnsAsk -> dgnsAsk.getDgnsTyCd().equals(dgnsTyCd)).collect(Collectors.toList());
        for (DgnsAsk dgnsAsk : filteredDgnsAskList) {
            DgnsSelection dgnsSelection = dgnsSelectionList
                    .stream()
                    .filter(ds -> ds.getDgnsAskId().equals(String.valueOf(dgnsAsk.getDgnsAskId())))
                    .collect(Collectors.toList())
                    .stream()
                    .findFirst().orElseThrow(RuntimeException::new);
            DgnsAns dgnsAns = dgnsAsk.getDgnsAnsList()
                    .stream()
                    .filter(da -> String.valueOf(da.getDgnsAnsId()).equals(dgnsSelection.getDgnsAnsId()))
                    .collect(Collectors.toList())
                    .stream()
                    .findFirst().orElseThrow(RuntimeException::new);
            totalScore += dgnsAns.getDgnsScore();
        }
        return totalScore;
    }

    public DgnsDtl findDgnsDtlByScore(String dgnsTyCd, List<DgnsDtl> dgnsDtlList, Double totalScore) {
        return dgnsDtlList.stream()
                .filter(dgnsDtl -> dgnsDtl.getDgnsTyCd().equals(dgnsTyCd))
                .collect(Collectors.toList())
                .stream()
                .filter(dgnsDtl -> dgnsDtl.isBetweenWithDgnsDtl(totalScore))
                .findFirst()
                .orElseThrow(RuntimeException::new);
    }

    public DgnsDtl findDgnsDtlById(List<DgnsDtl> dgnsDtlList, Long dgnsDtlId) {
        return dgnsDtlList.stream()
                .filter(dgnsDtl -> dgnsDtl.getDgnsDtlId().equals(dgnsDtlId))
                .findFirst()
                .orElseThrow(RuntimeException::new);
    }

    public String getDgnsResultText(User user, Dgns dgns) {
        StringBuilder result = new StringBuilder();
        if (user!= null && user.getUserNm() !=null) {
            result.append(user.getUserNm()).append("님은 ");
        } else {
            result.append("당신은 ");
        }

        result.append(dgns.getSkTy().getSkTyCd()).append(" 타입으로 ");
        result.append(dgns.getOdDgnsDtl().getDgnsCont()).append(", ");
        result.append(dgns.getSrDgnsDtl().getDgnsCont()).append(", ");
        result.append(dgns.getPnDgnsDtl().getDgnsCont()).append(", ");
        result.append(dgns.getWtDgnsDtl().getDgnsCont()).append("입니다.\n");

        result.append(dgns.getSkTy().getSkTyDtl());

        return result.toString();
    }

    public String getDgnsResultTitleText(Dgns dgns) {
        Integer cnt = dgns.getDgnsCnt();
        if (cnt != null) {
            return cnt+"회차 테스트 종합분석 결과";
        } else {
            return "진단 종합분석 결과";
        }
    }

    public String getDgnsResultTime(Dgns dgns) {
        LocalDateTime regDt = dgns.getRegDt();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH시 mm분");
        if (regDt == null) {
            ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Asia/Seoul"));
            return now.format(dateTimeFormatter);
        } else {
            return regDt.format(dateTimeFormatter);
        }
    }

    public List<DgnsSearch> skinTypeStats(DgnsSearch dgnsSearch) {
        return dgnsMapper.skinTypeStats(dgnsSearch);
    }

}
