package com.dbnt.faisp.main.userInfo.service;

import com.dbnt.faisp.config.Role;
import com.dbnt.faisp.main.userInfo.mapper.UserInfoMapper;
import com.dbnt.faisp.main.userInfo.model.*;
import com.dbnt.faisp.main.userInfo.repository.*;
import com.dbnt.faisp.util.ParamMap;

import lombok.RequiredArgsConstructor;

import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@RequiredArgsConstructor
public class UserInfoService implements UserDetailsService {

  private final UserInfoRepository userInfoRepository;
  private final UserInfoHistoryRepository userInfoHistoryRepository;
  private final DashboardConfigRepository dashboardConfigRepository;
  private final UserInfoMapper userInfoMapper;

  @Transactional
  public String insertUserInfo(UserInfo userInfo){
    if(userInfoRepository.findByUserId(userInfo.getUserId()).orElse(null) != null){
      return "userIdDuplication";
    }
    userInfo.setUserRole(Role.USER.getValue());
    userInfo.setUserStatus("USC002");
    userInfo.setPassword(convertPassword(userInfo.getPassword()));
    userInfo.setWrtDt(LocalDateTime.now());
    UserInfo result = userInfoRepository.save(userInfo);
    UserInfoHistory dbHis = userInfoHistoryRepository.findByUserSeq(result.getUserSeq());
    if(dbHis == null) {
      UserInfoHistory hisTmp = new UserInfoHistory();
      hisTmp.setUserSeq(result.getUserSeq());
      hisTmp.setVersionNo(1);
      hisTmp.setDicCode(result.getDicCode());
      hisTmp.setUserId(result.getUserId());
      hisTmp.setUserNm(result.getUserNm());
      hisTmp.setBirthDate(result.getBirthDate());
      hisTmp.setSex(result.getSex());
      hisTmp.setEmail(result.getEmail());
      hisTmp.setPhoneNo(result.getPhoneNo());
      hisTmp.setAreaCd(result.getAreaCd());
      hisTmp.setOgCd(result.getOgCd());
      hisTmp.setOfcCd(result.getOfcCd());
      hisTmp.setTitleCd(result.getTitleCd());
      hisTmp.setGroupCd(result.getGroupCd());
      hisTmp.setSeriesCd(result.getSeriesCd());
      hisTmp.setOfcHeadYn(result.getOfcHeadYn());
      hisTmp.setHiringCd(result.getHiringCd());
      hisTmp.setEmployCd(result.getEmployCd());
      hisTmp.setOutturnCd(result.getOutturnCd());
      hisTmp.setWorkCd(result.getWorkCd());
      hisTmp.setJobInCd(result.getJobInCd());
      hisTmp.setLanguageCd(result.getLanguageCd());
      hisTmp.setPoliceInDate(result.getPoliceInDate());
      hisTmp.setOrganInDate(result.getOrganInDate());
      hisTmp.setOfcInDate(result.getOfcInDate());
      hisTmp.setTitleInDate(result.getTitleInDate());
      hisTmp.setUserStatus(result.getUserStatus());
      hisTmp.setWrtOrgan(result.getOgCd());
      hisTmp.setWrtPart(result.getOfcCd());
      hisTmp.setWrtTitle(result.getTitleCd());
      hisTmp.setWrtUserSeq(result.getUserSeq());
      hisTmp.setWrtNm(result.getUserNm());
      hisTmp.setWrtDt(result.getWrtDt());
      userInfoHistoryRepository.save(hisTmp);
    }
    return result.getUserId();
  }
  @Transactional
  public void updateUserInfo(UserInfo loginUser,UserInfo userInfo){
    UserInfo savedInfo = userInfoRepository.findById(userInfo.getUserSeq()).orElse(null);
    if(savedInfo!=null){
      if(userInfo.getDicCode()!=null){
        savedInfo.setDicCode(userInfo.getDicCode());
      }
      if(userInfo.getUserNm()!=null){
        savedInfo.setUserNm(userInfo.getUserNm());
      }
      if(userInfo.getPassword()!=null && userInfo.getPassword()!=null){
        savedInfo.setPassword(convertPassword(userInfo.getPassword()));
      }
      if(userInfo.getPhoneNo()!=null){
        savedInfo.setPhoneNo(userInfo.getPhoneNo());
      }
      if(userInfo.getEmail()!=null){
        savedInfo.setEmail(userInfo.getEmail());
      }
      if(userInfo.getSex()!=null){
        savedInfo.setSex(userInfo.getSex());
      }
      if(userInfo.getOgCd()!=null){
        savedInfo.setOgCd(userInfo.getOgCd());
      }
      if(userInfo.getOfcCd()!=null){
        savedInfo.setOfcCd(userInfo.getOfcCd());
      }
      if(userInfo.getTitleCd()!=null){
        savedInfo.setTitleCd(userInfo.getTitleCd());
      }
      if(userInfo.getOutturnCd()!=null){
        savedInfo.setOutturnCd(userInfo.getOutturnCd());
      }
      if(userInfo.getSeriesCd()!=null){
        savedInfo.setSeriesCd(userInfo.getSeriesCd());
      }
      if(userInfo.getBirthDate()!=null){
        savedInfo.setBirthDate(userInfo.getBirthDate());
      }
      if(userInfo.getPoliceInDate()!=null){
        savedInfo.setPoliceInDate(userInfo.getPoliceInDate());
      }
      if(userInfo.getOrganInDate()!=null){
        savedInfo.setOrganInDate(userInfo.getOrganInDate());
      }
      if(userInfo.getOfcInDate()!=null){
        savedInfo.setOfcInDate(userInfo.getOfcInDate());
      }
      if(userInfo.getTitleInDate()!=null){
        savedInfo.setTitleInDate(userInfo.getTitleInDate());
      }
      if(userInfo.getLanguageCd()!=null){
        savedInfo.setLanguageCd(userInfo.getLanguageCd());
      }
      if(userInfo.getOfcHeadYn()!=null){
        savedInfo.setOfcHeadYn(userInfo.getOfcHeadYn());
      }
      if(userInfo.getUserRole()!=null){
        savedInfo.setUserRole(userInfo.getUserRole());
      }
      if(userInfo.getUserStatus()!=null){
        savedInfo.setUserStatus(userInfo.getUserStatus());
      }
      userInfoRepository.save(savedInfo);
      UserInfoHistory dbHis = userInfoHistoryRepository.findTopByUserSeqOrderByVersionNoDesc(savedInfo.getUserSeq());
      if(dbHis != null) {
        UserInfoHistory hisTmp = new UserInfoHistory();
        hisTmp.setUserSeq(savedInfo.getUserSeq());
        hisTmp.setVersionNo(dbHis.getVersionNo()+1);
        hisTmp.setDicCode(savedInfo.getDicCode());
        hisTmp.setUserId(savedInfo.getUserId());
        hisTmp.setUserNm(savedInfo.getUserNm());
        hisTmp.setBirthDate(savedInfo.getBirthDate());
        hisTmp.setSex(savedInfo.getSex());
        hisTmp.setEmail(savedInfo.getEmail());
        hisTmp.setPhoneNo(savedInfo.getPhoneNo());
        hisTmp.setAreaCd(savedInfo.getAreaCd());
        hisTmp.setOgCd(savedInfo.getOgCd());
        hisTmp.setOfcCd(savedInfo.getOfcCd());
        hisTmp.setTitleCd(savedInfo.getTitleCd());
        hisTmp.setGroupCd(savedInfo.getGroupCd());
        hisTmp.setSeriesCd(savedInfo.getSeriesCd());
        hisTmp.setOfcHeadYn(savedInfo.getOfcHeadYn());
        hisTmp.setHiringCd(savedInfo.getHiringCd());
        hisTmp.setEmployCd(savedInfo.getEmployCd());
        hisTmp.setOutturnCd(savedInfo.getOutturnCd());
        hisTmp.setWorkCd(savedInfo.getWorkCd());
        hisTmp.setJobInCd(savedInfo.getJobInCd());
        hisTmp.setLanguageCd(savedInfo.getLanguageCd());
        hisTmp.setPoliceInDate(savedInfo.getPoliceInDate());
        hisTmp.setOrganInDate(savedInfo.getOrganInDate());
        hisTmp.setOfcInDate(savedInfo.getOfcInDate());
        hisTmp.setTitleInDate(savedInfo.getTitleInDate());
        hisTmp.setUserStatus(savedInfo.getUserStatus());
        hisTmp.setWrtOrgan(loginUser.getOgCd());
        hisTmp.setWrtPart(loginUser.getOfcCd());
        hisTmp.setWrtTitle(loginUser.getTitleCd());
        hisTmp.setWrtUserSeq(loginUser.getUserSeq());
        hisTmp.setWrtNm(loginUser.getUserNm());
        hisTmp.setWrtDt(LocalDateTime.now());
        userInfoHistoryRepository.save(hisTmp);
      }
    }
  }

  public String updatePassword(UserInfo loginUser, UserInfo modifyInfo){
    Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder();
    if(passwordEncoder.matches(modifyInfo.getPassword(), loginUser.getPassword())){
      loginUser.setPassword(convertPassword(modifyInfo.getModifyPassword()));
      userInfoRepository.save(loginUser);
      return "OK";
    }else{
      return "passwordNotMatch";
    }
  }

  private String convertPassword(String password){
    Pbkdf2PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder();
    return passwordEncoder.encode(password);
  }

  @Override
  public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundException {
    return userInfoRepository.findByUserId(userId).orElseThrow(() -> new UsernameNotFoundException(userId));
  }

  public List<UserInfo> selectUserInfoList(UserInfo userInfo) {
    return userInfoMapper.selectUserInfoList(userInfo);
  }

  public Integer selectUserInfoListCnt(UserInfo userInfo) {
    return userInfoMapper.selectUserInfoListCnt(userInfo);
  }

  public UserInfo selectUserInfo(Integer userSeq) {
    return userInfoRepository.findByUserSeq(userSeq).orElse(null);
  }

  public UserInfo selectUserInfoToDicCode(String dicCode){
    return userInfoRepository.findByDicCode(dicCode).orElse(null);
  }

  @Transactional
  public int updateUserApproval(List<UserInfo> userInfo) {
    int cnt = 0;
    for(UserInfo user: userInfo) {
      UserInfo dbUserInfo = userInfoRepository.findById(user.getUserSeq()).orElse(null);
      if(dbUserInfo != null) {
        dbUserInfo.setUserStatus(user.getUserStatus());
        userInfoRepository.save(dbUserInfo);
        cnt++;
      }
    }
    return cnt;
  }
  @Transactional
  public int updateUserCompanion(List<UserInfo> userInfo) {
    int cnt = 0;
    for(UserInfo user: userInfo) {
      UserInfo dbUserInfo = userInfoRepository.findById(user.getUserSeq()).orElse(null);
      if(dbUserInfo != null) {
        dbUserInfo.setUserStatus(user.getUserStatus());
        userInfoRepository.save(dbUserInfo);
        cnt++;
      }
    }
    return cnt;
  }
  public void userDelete(List<UserInfo> userInfo) {
    userInfoRepository.deleteAll(userInfo);
  }
  public List<ParamMap> selectManagerList(ParamMap param) {
    return userInfoMapper.selectManagerList(param);
  }

  public List<DashboardConfig> getDashboardConfigList(Integer userSeq) {
    return userInfoMapper.selectDashboardConfigList(userSeq);
  }


  @Transactional
  public void saveDashboardConfigList(Integer userSeq, List<DashboardConfig> configList) {
    dashboardConfigRepository.deleteByUserSeq(userSeq);
    for(DashboardConfig config: configList){
      config.setUserSeq(userSeq);
    }
    dashboardConfigRepository.saveAll(configList);
  }

  public List<UserInfo> selectPoliceList(UserInfo userInfo) {
    return userInfoMapper.selectPoliceList(userInfo);
  }
  public Integer selectPoliceListCnt(UserInfo userInfo) {
    return userInfoMapper.selectPoliceListCnt(userInfo);
  }

  public List<UserInfoHistory> selectPoliceHisList(UserInfoHistory userInfoHistory) {
    return userInfoMapper.selectPoliceHisList(userInfoHistory);
  }

  public UserInfoHistory selectPoliceHistoryView(UserInfoHistory userInfoHistory) {
    return userInfoMapper.selectpoliceHistoryView(userInfoHistory);
  }
  public String selectUserStatus(UserInfoHistory userInfoHistory) {
    return userInfoRepository.getUserStatus(userInfoHistory.getUserSeq());
  }

}
