package cokr.xit.fims.levy.web;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.poi.ss.usermodel.CellStyle;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import cokr.xit.base.code.CommonCode;
import cokr.xit.base.docs.xls.CellDef;
import cokr.xit.base.docs.xls.Format;
import cokr.xit.base.docs.xls.Style;
import cokr.xit.base.docs.xls.XLSWriter;
import cokr.xit.base.user.dao.UserMapper;
import cokr.xit.base.web.ApplicationController;
import cokr.xit.fims.cmmn.service.bean.StngBean;
import cokr.xit.fims.cmmn.xls.FormatMaker;
import cokr.xit.fims.cmmn.xls.StyleMaker;
import cokr.xit.fims.levy.LevyQuery;
import cokr.xit.fims.levy.Rdct;
import cokr.xit.fims.levy.service.RdctService;
import cokr.xit.fims.task.Task;
import cokr.xit.foundation.data.DataObject;

/**과태료 감경 대장 서비스의 웹 컨트롤러
 *
 * <p>상세 설명:
 *
 * <pre>
 * ============ 변경 이력 ============
 * 2023-08-30    JoJH 최초 작성
 * ================================
 * </pre>
 */
@Controller
@RequestMapping(name="과태료 감경 관리", value=Levy02Controller.CLASS_URL)
public class Levy02Controller extends ApplicationController {

    public static final String CLASS_URL = "/levy/levy02";

    public class METHOD_URL {
        public static final String
              reductionMain         = "/010/main.do"                            // 과태료 감경 관리 메인 화면
            , getReductionList      = "/010/list.do"                            // 과태료 감경 대장 목록 조회
            , removeReduction       = "/010/remove.do"                          // 과태료 감경 대장 삭제
            , getReductionInfo      = "/020/info.do"                            // 과태료 감경 정보 조회
            , createReduction       = "/020/create.do"                          // 과태료 감경 대장 등럭
            , updateReduction       = "/020/update.do"                          // 과태료 감경 대장 수정
        ;
    }

    /**과태료 감경 대장 서비스*/
    @Resource(name="rdctService")
    private RdctService rdctService;
    @Resource(name="stngBean")
    private StngBean stngBean;
    @Resource(name="userMapper")
    protected UserMapper userMapper;

    /**과태료 감경 대장 관리 메인화면(levy/levy02010-main)을 연다.
     * 조건없는 {@link #getRdctList(RdctQuery) 과태료 감경 대장 조회 결과}를 포함시킨다.
     * @return /rdct/rdct-main
     */
    @RequestMapping(name="과태료 감경 관리 대장 메인", value=METHOD_URL.reductionMain)
    public ModelAndView reductionMain() {
        // View(jsp)에서 사용할 공통코드를 조회
        Map<String, List<CommonCode>> commonCodes = getCodesOf("FIM019", "FIM054");

        return new ModelAndView("fims/levy/levy02010-main")
            .addObject("pageName", "levy02010")                             // View(jsp)에서 사용할 id 뒤에 붙일 suffix
            .addObject("prefixUrl", CLASS_URL)                              // prefixUrl
            .addObject("sggCd", currentUser().getOrgID())                        // 시군구 코드(SGG_CD)
            .addObject("taskListForSgg", stngBean.filterTaskSectionCodeForSgg(commonCodes.get("FIM054")))    // 업무 구분 코드(TASK_SE_CD)
            .addObject("FIM019List", commonCodes.get("FIM019"))             // 감경 사유 구분 코드(RDCT_RSN_CD)
        ;
    }

    /**과태료 감경 대장 목록을 조회하여 반환한다.<br />
     * {@link RdctService#getRdctList(RdctQuery)} 참고
     * @param req 과태료 감경 대장 조회 조건
     * @return jsonView
     * <pre><code> {
     *     "rdctList": [과태료 감경 대장 목록]
     *     "rdctStart": 과태료 감경 대장 목록 시작 인덱스
     *     "rdctFetch": 한 번에 가져오는 과태료 감경 대장 목록 수
     *     "rdctTotal": 조회 결과 찾은 전체 과태료 감경 대장 수
     * }</code></pre>
     */
    @Task
    @RequestMapping(name="과태료 감경 대장 목록 조회", value=METHOD_URL.getReductionList)
    public ModelAndView getRdctList(LevyQuery req) {
        if (!"xls".equals(req.getDownload())) {
            List<?> result = rdctService.getRdctList(setFetchSize(req));
            return setPagingInfo(new ModelAndView("jsonView"), result, "");
        } else {
            // 현재 날짜 구하기
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
            String dateTime = dateFormat.format(System.currentTimeMillis());

            List<CellDef> cellDefs = fromJson(req.getCellDefs(), CellDef.listType());

            XLSWriter xlsx = new XLSWriter().worksheet(0);
            Format format = new Format(xlsx);
            CellStyle center = format.cellStyle(Style.CENTER);
            CellStyle numeric = format.n_nn0();
            CellStyle dateYMD = format.yyyy_mm_dd();
            CellStyle dateDT = format.yyyy_mm_dd_hh_mm_ss();

            List<DataObject> list = rdctService.getRdctList(req.setFetchSize(0));

            Map<String,Object> valueMap = new HashMap<String,Object>();
            valueMap.put("업무구분", format.of("TASK_SE_NM").style(center));
            valueMap.put("감경일자", FormatMaker.yyyy_mm_dd(format, "RDCT_YMD").style(dateYMD));
            valueMap.put("감경사유", format.of("RDCT_RSN_NM"));
            valueMap.put("기타내용", format.of("ETC_CN"));
            valueMap.put("단속일시", FormatMaker.yyyy_mm_dd_hh_mm_ss(format, "CRDN_YMD_TM").style(dateDT));
            valueMap.put("차량번호", format.of("VHRNO"));
            valueMap.put("납부자구분", format.of("RTPYR_SE_NM").style(center));
            valueMap.put("납부자번호", format.of("RTPYR_NO").style(center));
            valueMap.put("납부자명", format.of("RTPYR_NM"));
            valueMap.put("단속법정동", format.of("CRDN_STDG_NM").style(center));
            valueMap.put("단속장소", format.of("CRDN_PLC"));
            valueMap.put("상세단속장소", format.of("DTL_CRDN_PLC"));
            valueMap.put("단속원금", format.of("FFNLG_CRDN_AMT").style(numeric));
            valueMap.put("감경금액", format.of("RDCT_AMT").style(numeric));
            valueMap.put("과태료금액", format.of("FFNLG_AMT").style(numeric));
            valueMap.put("최종금액", format.of("LAST_AMT").style(numeric));
            valueMap.put("처리상태", format.of("CRDN_STTS_NM"));
            valueMap.put("단속특별구역", format.of("CRDN_SPAREA_NM").style(center));
            valueMap.put("사용연료", format.of("USE_FUEL_NM").style(center));
            valueMap.put("주차가능여부", format.of("PRK_PSBLTY_RSLT_NM").style(center));
            valueMap.put("등록일시", FormatMaker.yyyy_mm_dd_hh_mm_ss(format, "REG_DT").style(dateDT));
            valueMap.put("등록사용자", format.of("RGTR_NM").style(center));
            valueMap.put("수정일시", FormatMaker.yyyy_mm_dd_hh_mm_ss(format, "MDFCN_DT").style(dateDT));
            valueMap.put("수정사용자", format.of("MDFR_NM").style(center));

            CellDef.setValues(cellDefs, valueMap);

            xlsx.cell(0, 0).value("과태료감경").value(center).merge(0, cellDefs.size() - 1)
                .cell(3, 0).rowValues(CellDef.header(cellDefs, () -> StyleMaker.headerStyle(xlsx)))
                .cell(4, 0).values(list, CellDef.values(cellDefs.stream().map(i -> {if(i.getValue() instanceof Format) {i.setField(null);}; return i;}).toList()));

            return new ModelAndView("downloadView")
                .addObject("download", xlsx.getDownloadable().setFilename("과태료감경" + "_목록_" + dateTime + ".xlsx"));
        }
    }

    /**지정한 ID의 과태료 감경 정보(info)를 반환한다.
     * @param req 과태료 감경 대장 조회 조건
     * @return fims/levy/levy02020-info 또는 jsonView
     * <pre>{
     *     "rdctInfo": 과태료 감경 정보
     * }</pre>
     */
    @Task
    @RequestMapping(name="과태료 감경 정보 조회", value=METHOD_URL.getReductionInfo)
    public ModelAndView getRdctInfo(HttpServletRequest hReq, LevyQuery req) {
        // 상세 정보 조회
        DataObject rdctInfo = rdctService.getRdctInfo(req);

        if (req.getCallPurpose().equals("create")) {                            // 등록
            if (!rdctInfo.string("RDCT_ID").equals("")) {
                return new ModelAndView("jsonView")
                	.addObject("rtnMsg", "이미 등록된 과태료 감경 정보가 있습니다.");
            } else if (rdctInfo.string("RTPYR_ID").equals("")) {
                return new ModelAndView("jsonView")
                	.addObject("rtnMsg", "납부자 정보가 없습니다.");
            }
        } else if (req.getCallPurpose().equals("update")) {                     // 수정
            if (rdctInfo.string("RDCT_ID").equals("")) {
                return new ModelAndView("jsonView")
                	.addObject("rtnMsg", "조회된 과태료 감경 정보가 없습니다.");
            }
        }

        // View(jsp)에서 사용할 공통코드를 조회
        Map<String, List<CommonCode>> commonCodes = getCodesOf("FIM019");

        boolean json = jsonResponse();
        return new ModelAndView(json ? "jsonView" : "fims/levy/levy02020-info")
            .addObject("callPurpose", req.getCallPurpose())             // 호출 용도
            .addObject("pageName", "levy02020")                         // jsp pageName
            .addObject("prefixUrl", CLASS_URL)                          // prefixUrl
            .addObject("FIM019List", commonCodes.get("FIM019"))         // 감경 사유 구분 코드(RDCT_RSN_CD)
            .addObject("Info", json ? rdctInfo : toJson(rdctInfo))
        ;
    }

    /**과태료 감경 대장를 등록한다.
     * @param rdct 과태료 감경 대장 정보
     * @return jsonView
     * <pre><code> {
     *     "saved": 등록되었으면 true, 그렇지 않으면 false
     * }</code></pre>
     */
    @Task
    @RequestMapping(name="과태료 감경 대장 등록", value=METHOD_URL.createReduction)
    public ModelAndView createRdct(Rdct rdct) {
        String rtnMsg = rdctService.createRdct(rdct);

        return new ModelAndView("jsonView")
            .addObject("saved", rtnMsg.contains("[S]"))
            .addObject("rtnMsg", rtnMsg);
    }

    /**과태료 감경 대장 정보를 수정한다.
     * @param rdct 과태료 감경 대장 정보
     * @return jsonView
     * <pre><code> {
     *     "saved": 수정되었으면 true, 그렇지 않으면 false
     * }</code></pre>
     */
    @Task
    @RequestMapping(name="과태료 감경 대장 수정", value=METHOD_URL.updateReduction)
    public ModelAndView updateRdct(Rdct rdct) {
        String rtnMsg = rdctService.updateRdct(rdct);

        return new ModelAndView("jsonView")
            .addObject("saved", rtnMsg.contains("[S]"))
            .addObject("rtnMsg", rtnMsg);
    }

    /**지정한 과태료 감경 대장를 제거한다.
     * @param rdctId 과태료 감경 대장 ID
     * @return jsonView
     * <pre><code> {
     *     "affected": 저장된 정보수
     *     "saved": 저장되었으면 true, 그렇지 않으면 false
     * }</code></pre>
     */
    @Task
    @RequestMapping(name="과태료 감경 대장 삭제", value=METHOD_URL.removeReduction)
    public ModelAndView removeRdct(Rdct rdct) {
        String rtnMsg = "";

        if (rdct.getRdctIds() == null || rdct.getRdctIds().length < 1) {
            rtnMsg = rdctService.removeRdct(rdct);
        } else {
            // 감경 IDs 만큼 감경 삭제 반복..
            for (String rdctId : rdct.getRdctIds()) {
                Rdct deltRdct = new Rdct();
                deltRdct.setRdctId(rdctId);
                deltRdct.setDelRsn(rdct.getDelRsn());

                // 감경 삭제 호출
                rtnMsg = rdctService.removeRdct(deltRdct);
                if (!rtnMsg.contains("[S]"))                                    // 오류가 발생하였으면 종료..
                    break;
            }
        }

        return new ModelAndView("jsonView")
            .addObject("saved", rtnMsg.contains("[S]"))
            .addObject("rtnMsg", rtnMsg);
    }
}