package com.oqpo.api.service.oper;


import com.oqpo.api.entity.oper.UserAuthInfoEntity;
import com.oqpo.api.entity.oper.UserMngEntity;
import com.oqpo.api.enums.SystemMessageCode;
import com.oqpo.api.exception.GlobalException;
import com.oqpo.api.mapper.oper.UserMngMapper;
import com.oqpo.api.service.CommonService;
import com.oqpo.api.web.dto.request.GridRequest;
import com.oqpo.api.web.dto.request.oper.usermng.SavePrivateUserRequest;
import com.oqpo.api.web.dto.request.oper.usermng.SaveUserRequest;
import com.oqpo.api.web.dto.response.GridResponse;
import com.oqpo.api.web.dto.response.oper.usermng.UserAuthResponse;
import com.oqpo.api.web.dto.response.oper.usermng.UserInfoResponse;
import com.oqpo.api.web.dto.response.oper.usermng.UserMngSearchResponse;
import com.oqpo.api.web.dto.response.oper.usermng.UserPopSearchResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserMngService extends CommonService {

    @Autowired
    private UserMngMapper userMngMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    /*
      사용자 검색 리스트 조회
     */
    public GridResponse userSearchGridList(String afflShopId, String brandId, String fromDt, String toDt, String sUserNm, String sUserStatCd, String sAuthTpCd, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();
        int gridRecords = userMngMapper.selectUserGridListCnt(afflShopId, brandId, fromDt, toDt, sUserNm, sUserStatCd, sAuthTpCd);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<UserMngEntity> entities = userMngMapper.selectUserGridList(afflShopId, brandId, fromDt, toDt, sUserNm, sUserStatCd, sAuthTpCd, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> UserMngSearchResponse.builder()
                        .viewCd("R")
                        .afflShopId(m.getAfflShopId() == null ? "" : m.getAfflShopId() )
                        .afflShopNm(m.getAfflShopNm() == null ? "" : m.getAfflShopNm() )
                        .brandId(m.getBrandId() == null ? "" : m.getBrandId() )
                        .brandNm(m.getBrandNm() == null ? "" : m.getBrandNm() )
                        .userId(m.getUserId())
                        .userNm(m.getUserNm())
                        .telNo(m.getTelNo())
                        .email(m.getEmail())
                        .userStatCd(m.getUserStatCd())
                        .userStatDt(m.getUserStatDt())
                        .userStatNm(m.getUserStatNm())
                        .addDt(m.getAddDt())
                        .lastLoginDt(m.getLastLoginDt() == null ? "" : m.getLastLoginDt())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /*
    사용자 id 중복체크
     */
    public String selectUserIdDupYn(String userId) throws Exception {
        return userMngMapper.selectUserIdDupYn(userId);
    }

    /*
      사용자관리 - 저장
     */
    @Transactional
    public void saveUser(String userId, SaveUserRequest saveUserRequest) throws Exception {
        try {

            // 기본정보 저장
            UserMngEntity entity = new UserMngEntity();
            entity.setUserId(saveUserRequest.getUserId());
            entity.setUserNm(saveUserRequest.getUserNm());
            entity.setTelNo(saveUserRequest.getTelNo());
            entity.setEmail(saveUserRequest.getEmail());
            entity.setSystemAdminYn("N");
            entity.setUserStatCd(saveUserRequest.getUserStatCd());

            entity.setAfflShopId(saveUserRequest.getAfflShopId());
            entity.setBrandId(saveUserRequest.getBrandId());

            if ("C".equals(saveUserRequest.getViewCd())) {

                //신규일경우만 권한
                if ("".equals(saveUserRequest.getAfflShopId()) && "".equals(saveUserRequest.getBrandId())) {
                    entity.setAuthTpCd("10");
                } else if (!"".equals(saveUserRequest.getAfflShopId()) && "".equals(saveUserRequest.getBrandId())) {
                    entity.setAuthTpCd("30");
                } else if (!"".equals(saveUserRequest.getAfflShopId()) && !"".equals(saveUserRequest.getBrandId())) {
                    entity.setAuthTpCd("40");
                }

                //패스워드 암호화
                String password = passwordEncoder.encode(saveUserRequest.getUserPw());//aes256.aesEncode(entity.getTelNo());
                entity.setUserPw(password);
                userMngMapper.insertUserInfo(userId, entity);
            } else if ("U".equals(saveUserRequest.getViewCd())) {
                userMngMapper.updateUserInfo(userId, entity);
            }
            // 사용자 권한정보 저장
            // 신규건
            if (saveUserRequest.getGridInsertData() != null) {
                List<UserAuthInfoEntity> gridInsertData = saveUserRequest.toUserAuthEntities(saveUserRequest.getGridInsertData());
                if (gridInsertData.size() > 0) {
                    userMngMapper.insertUserAuth(userId, gridInsertData);
                }
            }

            // 삭제건
            if (saveUserRequest.getGridDeleteData() != null) {
                List<UserAuthInfoEntity> gridDeleteData = saveUserRequest.toUserAuthEntities(saveUserRequest.getGridDeleteData());
                if (gridDeleteData.size() > 0) {
                    userMngMapper.deleteUserAuth(entity.getUserId(), gridDeleteData);
                }
            }

        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }

    /*
   사용자 pw 초기화
    */
    @Transactional
    public String updateInitUserPw(String userId) throws Exception {
        // 사용자 정보를 가져옴
        try {
            UserMngEntity entity = userMngMapper.selectUserInfo(userId);
            String password = passwordEncoder.encode(entity.getTelNo().replace("-", ""));//aes256.aesEncode(entity.getTelNo());
            userMngMapper.updateInitUserPw(userId, password);
            return password;
        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }

    /*
    사용자 정보 가져오기
     */
    public UserInfoResponse selectUserInfo(String userId) throws Exception {
        return UserInfoResponse.toDTO(userMngMapper.selectUserInfo(userId));
    }

    /*
    사용자 권한 리스트
     */
    public GridResponse selectUserAuthGridList(String userId, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();
        int gridRecords = userMngMapper.selectUserAuthGridListCnt(userId);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<UserAuthInfoEntity> entities = userMngMapper.selectUserAuthGridList(userId, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> UserAuthResponse.builder()
                        .viewCd("R")
                        .userId(m.getUserId())
                        .authNo(m.getAuthNo())
                        .authNm(m.getAuthInfo().getAuthNm())
                        .useYn(m.getAuthInfo().getUseYn())
                        .useYnNm(m.getAuthInfo().getUseYnNm())
                        .addDt(m.getAddDt())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /*
      사용자 팝업 검색 리스트 조회
     */
    public GridResponse selectPopUserGridList(String sAfflShopId, String sBrandId, String sUserId, String sUserNm, String sUserStatCd, GridRequest gridRequest) throws Exception {
        int gridPage = gridRequest.getGridPage();
        int gridSize = gridRequest.getGridSize();
        int gridRecords = userMngMapper.selectPopUserGridCnt(sAfflShopId, sBrandId,  sUserId, sUserNm, sUserStatCd);
        int gridTotal = fnCalculateGridTotal(gridSize, gridRecords);
        List<UserMngEntity> entities = userMngMapper.selectPopUserGridList(sAfflShopId, sBrandId, sUserId, sUserNm, sUserStatCd, gridRequest);
        List<Object> gridRows = entities.stream()
                .map(m -> UserPopSearchResponse.builder()
                        .viewCd("R")
                        .userId(m.getUserId())
                        .userNm(m.getUserNm())
                        .userStatNm(m.getUserStatNm())
                        .build())
                .collect(Collectors.toList());
        return GridResponse.toDTO(gridPage, gridTotal, gridRecords, gridRows);
    }

    /*
      사용자 최종 로그인 날짜 정보
     */
    @Transactional
    public void updateLoginDt(String userId) throws Exception {
        try {
                userMngMapper.updateLoginDt(userId);
        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }

    /*
      사용자 개인정보 수정 저장
     */
    @Transactional
    public void updatePrivateUserInfo(String userId, SavePrivateUserRequest savePrivateUserRequest) throws Exception {
        try {
            UserMngEntity entity = new UserMngEntity();
            entity.setUserId(savePrivateUserRequest.getUserId());
            entity.setTelNo(savePrivateUserRequest.getTelNo());
            entity.setEmail(savePrivateUserRequest.getEmail());
            userMngMapper.updatePrivateUserInfo(userId, entity);
        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }

    /*
      사용자 패스워드 변경
     */
    @Transactional
    public void updateChpPwUser(String userId, String password, String  chgPassword) throws Exception {
        try {
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(userId, password);
            Authentication authentication = authenticationManager.authenticate(token);
            chgPassword = passwordEncoder.encode(chgPassword);
            userMngMapper.updateInitUserPw(userId, chgPassword);
        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new GlobalException(SystemMessageCode.ERR_PW);
            //throw new RuntimeException();
        }
    }


    /*
   사용자 pw 변경
    */
    @Transactional
    public void updateChgUserPw(String userId, String newPw) throws Exception {
        try {
            String password = passwordEncoder.encode(newPw);//aes256.aesEncode(entity.getTelNo());
            userMngMapper.updateInitUserPw(userId, password);
        } catch (GlobalException e) {
            e.getStackTrace();
            throw new GlobalException(e.getSystemMessageCode());
        } catch (Exception e) {
            e.getStackTrace();
            throw new RuntimeException();
        }
    }

    /*
    모바일 사용자 정보 가져오기
     */
    public UserMngEntity selectMobileUserInfo(String userId) throws Exception {
        return userMngMapper.selectUserInfo(userId);
    }

}
