package com.dbnt.kcscbackend.admin.config;

import com.dbnt.kcscbackend.admin.config.entity.TcMenu;
import com.dbnt.kcscbackend.commonCode.entity.TcCodeGrp;
import com.dbnt.kcscbackend.commonCode.entity.TcCodeItem;
import com.dbnt.kcscbackend.admin.config.service.AdminConfigService;
import com.dbnt.kcscbackend.auth.entity.LoginVO;
import com.dbnt.kcscbackend.commonCode.service.CommonCodeService;
import com.dbnt.kcscbackend.config.common.BaseController;
import com.dbnt.kcscbackend.config.common.ResponseCode;
import com.dbnt.kcscbackend.config.common.ResultVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequiredArgsConstructor
@RequestMapping("/admin/config")
@Tag(name="AdminConfigController", description = "사이트관리 환결설정 메뉴 컨트롤러")
public class AdminConfigController extends BaseController {

  private final AdminConfigService adminConfigService;
  private final CommonCodeService commonCodeService;

  @Operation(
      summary = "기본코드 그룹 조회",
      description = "기본코드 그룹 조회",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "조회 성공"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.GET, value = "/code-grp")
  public ResultVO getCodeGrp() throws Exception{
    ResultVO resultVO = new ResultVO();
    Map<String, Object> resultMap = new HashMap<>();
    resultMap.put("codeGrpList", adminConfigService.selectCodeGrpList());
    resultVO.setResult(resultMap);
    return resultVO;
  }

  @Operation(
      summary = "기본코드 그룹 저장",
      description = "기본코드 그룹 저장",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "저장 성공"),
      @ApiResponse(responseCode = "303", description = "만료된 토큰"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.POST, value = "/code-grp", consumes = MediaType.APPLICATION_JSON_VALUE)
  public ResultVO addCodeGrp(@RequestBody TcCodeGrp codeGrp, @AuthenticationPrincipal LoginVO user) throws Exception{
    ResultVO resultVO = new ResultVO();
    if(user == null){
      resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
    }else{
      if(!user.getUserSe().equals("ACC_TP01")){
        resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
      }else if(codeGrp.getGrpCd().isEmpty()){
        resultVO.setResultCode(ResponseCode.INPUT_CHECK_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.INPUT_CHECK_ERROR.getMessage());
      }else{
        codeGrp.setFrstCrtDt(LocalDateTime.now());
        codeGrp.setFrstCrtId(user.getId());
        codeGrp.setUseYn("Y");
        String result = adminConfigService.addCodeGrp(codeGrp);
        if(result.equals("isSaved")){
          resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
          resultVO.setResultMessage("중복되는 코드그룹이 있습니다.");
        }else{
          resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
        }
      }
    }
    return resultVO;
  }

  @Operation(
      summary = "기본코드 그룹 수정",
      description = "기본코드 그룹 수정",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "수정 성공"),
      @ApiResponse(responseCode = "303", description = "만료된 토큰"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.PUT, value = "/code-grp", consumes = MediaType.APPLICATION_JSON_VALUE)
  public ResultVO modifyCodeGrp(@RequestBody TcCodeGrp codeGrp, @AuthenticationPrincipal LoginVO user) throws Exception{
    ResultVO resultVO = new ResultVO();
    if(user == null){
      resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
    }else{
      if(!user.getUserSe().equals("ACC_TP01")){
        resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
      }else if(codeGrp.getGrpCd().isEmpty()){
        resultVO.setResultCode(ResponseCode.INPUT_CHECK_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.INPUT_CHECK_ERROR.getMessage());
      }else{
        codeGrp.setLastChgDt(LocalDateTime.now());
        codeGrp.setLastChgId(user.getId());
        String result = adminConfigService.modifyCodeGrp(codeGrp);
        if(result.equals("modified")){
          resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
        }else{
          resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
        }
      }
    }
    return resultVO;
  }

  @Operation(
      summary = "기본코드 아이템 조회",
      description = "기본코드 아이템 조회",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "조회 성공"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.GET, value = "/code-item")
  public ResultVO getCodeItem(String grpCd) throws Exception{
    ResultVO resultVO = new ResultVO();
    Map<String, Object> resultMap = new HashMap<>();
    resultMap.put("codeItemList", adminConfigService.selectCodeItemList(grpCd));
    resultVO.setResult(resultMap);
    return resultVO;
  }

  @Operation(
      summary = "기본코드 아이템 저장",
      description = "기본코드 아이템 저장",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "저장 성공"),
      @ApiResponse(responseCode = "303", description = "만료된 토큰"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.POST, value = "/code-item", consumes = MediaType.APPLICATION_JSON_VALUE)
  public ResultVO addCodeItem(@RequestBody TcCodeItem codeItem, @AuthenticationPrincipal LoginVO user) throws Exception{
    ResultVO resultVO = new ResultVO();
    if(user == null){
      resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
    }else{
      if(!user.getUserSe().equals("ACC_TP01")){
        resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
      }else if(codeItem.getGrpCd()==null || codeItem.getGrpCd().isEmpty()){
        resultVO.setResultCode(ResponseCode.INPUT_CHECK_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.INPUT_CHECK_ERROR.getMessage());
      }else{
        codeItem.setFrstCrtDt(LocalDateTime.now());
        codeItem.setFrstCrtId(user.getId());
        codeItem.setUseYn("Y");
        String result = adminConfigService.addCodeItem(codeItem);
        if(result.equals("isSaved")){
          resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
          resultVO.setResultMessage("중복되는 코드가 있습니다.");
        }else{
          resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
        }
      }
    }
    return resultVO;
  }

  @Operation(
      summary = "기본코드 아이템 수정",
      description = "기본코드 아이템 수정",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "수정 성공"),
      @ApiResponse(responseCode = "303", description = "만료된 토큰"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.PUT, value = "/code-item", consumes = MediaType.APPLICATION_JSON_VALUE)
  public ResultVO modifyCodeItem(@RequestBody TcCodeItem codeItem, @AuthenticationPrincipal LoginVO user) throws Exception{
    ResultVO resultVO = new ResultVO();
    if(user == null){
      resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
    }else{
      if(!user.getUserSe().equals("ACC_TP01")){
        resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
      }else if(codeItem.getGrpCd().isEmpty()){
        resultVO.setResultCode(ResponseCode.INPUT_CHECK_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.INPUT_CHECK_ERROR.getMessage());
      }else{
        codeItem.setLastChgDt(LocalDateTime.now());
        codeItem.setLastChgId(user.getId());
        String result = adminConfigService.modifyCodeItem(codeItem);
        if(result.equals("modified")){
          resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
        }else{
          resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
        }
      }
    }
    return resultVO;
  }

  @Operation(
      summary = "메뉴 조회",
      description = "메뉴 조회",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "조회 성공"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.GET, value = "/menu-mgt")
  public ResultVO getMenuMgt(){
    ResultVO resultVO = new ResultVO();
    Map<String, Object> resultMap = new HashMap<>();
    resultMap.put("menuList", adminConfigService.selectMenuList());
    resultVO.setResult(resultMap);
    return resultVO;
  }

  @Operation(
      summary = "메뉴 저장",
      description = "메뉴 저장",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "저장 성공"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.PUT, value = "/menu-mgt")
  public ResultVO saveMenuMgt(@RequestBody @Valid TcMenu menu, Errors errors, @AuthenticationPrincipal LoginVO user){
    ResultVO resultVO = new ResultVO();
    if(user == null){
      resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
    }else {
      menu.setRoleGrpId(menu.getMenuTypeCd().equals("MNU_0000")?"ADMIN_USER":"ALL_USER");
      if(errors.hasErrors()){
        StringBuilder msg = new StringBuilder();
        for(FieldError error: errors.getFieldErrors()){
          msg.append(error.getDefaultMessage());
          msg.append("\n");
        }
        resultVO.setResultCode(ResponseCode.INPUT_CHECK_ERROR.getCode());
        resultVO.setResultMessage(msg.toString());
      }else if (!user.getUserSe().equals("ACC_TP01")) {
        resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
      } else {
        adminConfigService.saveMenu(menu, user.getId());
        resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
      }
    }
    return resultVO;
  }

  @Operation(
      summary = "메뉴 삭제",
      description = "메뉴 삭제",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "삭제 성공"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.DELETE, value = "/menu-mgt")
  public ResultVO removeMenuMgt(@RequestBody TcMenu menu, @AuthenticationPrincipal LoginVO user){
    ResultVO resultVO = new ResultVO();
    if(user == null){
      resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
    }else {
      if (!user.getUserSe().equals("ACC_TP01")) {
        resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
      } else {
        String result = adminConfigService.deleteMenu(menu.getMenuId(), user.getId());
        if(result==null){
          resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
        }else if(result.equals("notFind")){
          resultVO.setResultCode(ResponseCode.SAVE_ERROR.getCode());
          resultVO.setResultMessage("대상이 존재하지 않습니다.");
        }
      }
    }
    return resultVO;
  }

  @Operation(
      summary = "메뉴 권한 조회",
      description = "메뉴 권한 조회",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "조회 성공"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.GET, value = "/menu-auth-mgt")
  public ResultVO getMenuAuthMgt(){
    ResultVO resultVO = new ResultVO();
    Map<String, Object> resultMap = new HashMap<>();
    resultMap.put("menuList", adminConfigService.selectMenuAuthList());
    resultMap.put("roleList", commonCodeService.selectCodeItemList("ROLE"));
    resultVO.setResult(resultMap);
    return resultVO;
  }

  @Operation(
      summary = "메뉴 권한 수정",
      description = "메뉴 권한 수정",
      tags = {"AdminConfigController"}
  )
  @ApiResponses(value = {
      @ApiResponse(responseCode = "200", description = "수정 성공"),
      @ApiResponse(responseCode = "403", description = "인가된 사용자가 아님")
  })
  @RequestMapping(method = RequestMethod.PUT, value = "/menu-auth-mgt")
  public ResultVO editMenuAuthMgt(@RequestBody TcMenu menu, @AuthenticationPrincipal LoginVO user){
    ResultVO resultVO = new ResultVO();
    if(user == null){
      resultVO.setResultCode(ResponseCode.TOKEN_EXPIRED.getCode());
    }else {
      if (!user.getUserSe().equals("ACC_TP01")) {
        resultVO.setResultCode(ResponseCode.AUTH_ERROR.getCode());
        resultVO.setResultMessage(ResponseCode.AUTH_ERROR.getMessage());
      } else {
        adminConfigService.editMenuAuth(menu);
        resultVO.setResultCode(ResponseCode.SUCCESS.getCode());
      }
    }
    return resultVO;
  }

}
