package cokr.xit.fims.excl.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.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.excl.LevyExcl;
import cokr.xit.fims.excl.LevyExclQuery;
import cokr.xit.fims.excl.service.LevyExclService;
import cokr.xit.fims.task.Task;
import cokr.xit.foundation.data.DataObject;

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

    public static final String CLASS_URL = "/excl/excl01";

    public class METHOD_URL {
        public static final String
              levyExclusionMain         = "/010/main.do"                        // 부과 제외 관리 메인 화면
            , getLevyExclusionList      = "/010/list.do"                        // 부과 제외 대장 목록 조회
            , removeLevyExclusion       = "/010/remove.do"                      // 부과 제외 대장 삭제
            , getLevyExclusionInfo      = "/020/info.do"                        // 부과 제외 대장 상세 조회
            , createLevyExclusion       = "/020/create.do"                      // 부과 제외 대장 등록
            , updateLevyExclusion       = "/020/update.do"                      // 부과 제외 대장 수정
        ;
    }

    /**부과제외 대장 서비스*/
    @Resource(name = "levyExclService")
    protected LevyExclService levyExclService;
    /**설정 정보 Bean */
    @Resource(name = "stngBean")
    private StngBean stngBean;

    /**부과제외 관리 메인화면(fims/excl/excl01/010-main)을 연다.
     *
     * @return /fims/excl/excl01010
     */
    @RequestMapping(name = "부과제외 관리 메인", value=METHOD_URL.levyExclusionMain)
    public ModelAndView levyExclusionMain() {
        // View(jsp)에서 사용할 공통코드를 조회
        Map<String, List<CommonCode>> commonCodes = getCodesOf("FIM021", "FIM022", "FIM054");

        return addCodes(commonCodes, new ModelAndView("fims/excl/excl01010-main"), "FIM021", "FIM022")
            .addObject("pageName", "excl01010")                             // 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("FIM021List", commonCodes.get("FIM021"))             // 부과 제외 구분 코드(LEVY_EXCL_SE_CD)
            .addObject("FIM022List", commonCodes.get("FIM022"))             // 부과 제외 사유 코드(LEVY_EXCL_RSN_CD)
        ;
    }

    /**부과제외 대장 목록을 조회하여 반환한다.
     * {@link LevyExclService#getLevyExclList(LevyExclQuery)} 참고
     * @param req 부과제외 대장 조회 조건
     * @return jsonView
     * <pre><code> {
     *     "levyExclList": [부과제외 대장 목록]
     *     "levyExclStart": 부과제외 대장 목록 시작 인덱스
     *     "levyExclFetch": 한 번에 가져오는 부과제외 대장 목록 수
     *     "levyExclTotal": 조회 결과 찾은 전체 부과제외 대장 수
     * }</code></pre>
     */
    @Task
    @RequestMapping(name = "부과제외 대장 목록 조회", value=METHOD_URL.getLevyExclusionList)
    public ModelAndView getLevyExclusionList(LevyExclQuery req) {
        if (!"xls".equals(req.getDownload())) {
            List<?> result = levyExclService.getLevyExclList(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 left = format.cellStyle(Style.LEFT);
            CellStyle numeric = format.n_nn0();
            CellStyle dateYMD = format.yyyy_mm_dd();
            CellStyle dateDT = format.yyyy_mm_dd_hh_mm_ss();

            List<DataObject> list = levyExclService.getLevyExclList(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, "LEVY_EXCL_YMD").style(dateYMD));
            valueMap.put("부과제외구분", format.of("LEVY_EXCL_SE_NM").style(center));
            valueMap.put("부과제외사유", format.of("LEVY_EXCL_RSN_NM"));
            valueMap.put("기타내용", format.of("ETC_CN"));
            valueMap.put("민원신청번호", format.of("CVLCPT_APLY_NO").style(center));
            valueMap.put("민원접수번호", format.of("CVLCPT_RCPT_NO").style(center));
            valueMap.put("민원접수일자", FormatMaker.yyyy_mm_dd(format, "CVLCPT_RCPT_YMD").style(dateYMD));
            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("VLTN_ARTCL"));
            valueMap.put("단속원금", format.of("FFNLG_CRDN_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("우편번호", format.of("ZIP").style(center));
            valueMap.put("주소", format.of("ADDR"));
            valueMap.put("상세주소", format.of("DTL_ADDR"));
            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/excl/excl01020-info 또는 jsonView
     * <pre>{
     *     "levyExclInfo": 부과제외 정보
     * }</pre>
     */
    @Task
    @RequestMapping(name = "부과제외 정보 상세 조회", value=METHOD_URL.getLevyExclusionInfo)
    public ModelAndView getLevyExclusionInfo(HttpServletRequest hReq, LevyExclQuery req) {
        // 상세 정보 조회
        DataObject levyExclInfo = levyExclService.getLevyExclInfo(req);
        boolean empty = isEmpty(levyExclInfo.string("LEVY_EXCL_ID"));
        if (req.getCallPurpose().equals("create")) {                            // 등록
            if (!empty) {
                return new ModelAndView("jsonView")
                	.addObject("rtnMsg", "이미 등록된 부과제외 정보가 있습니다.")
                    .addObject("message", "이미 등록된 부과제외 정보가 있습니다.");
            }
        } else if (req.getCallPurpose().equals("update")) {
            if (empty) {               // 수정
                return new ModelAndView("jsonView")
                	.addObject("rtnMsg", "조회된 부과제외 정보가 없습니다.")
                    .addObject("message", "조회된 부과제외 정보가 없습니다.");
            }
        }
        // View(jsp)에서 사용할 공통코드를 조회
        Map<String, List<CommonCode>> commonCodes = getCodesOf("FIM021", "FIM022");

        boolean json = jsonResponse();
        return addCodes(commonCodes, new ModelAndView(json ? "jsonView" : "fims/excl/excl01020-info"), "FIM021", "FIM022")
            .addObject("callPurpose", req.getCallPurpose())                 // 호출 용도
            .addObject("pageName", "excl01020")                             // jsp pageName
            .addObject("prefixUrl", CLASS_URL)                              // prefixUrl
            .addObject("FIM021List", commonCodes.get("FIM021"))             // 부과 제외 구분 코드(LEVY_EXCL_SE_CD)
            .addObject("FIM022List", commonCodes.get("FIM022"))             // 부과 제외 사유 코드(LEVY_EXCL_RSN_CD)
            .addObject("Info", json ? levyExclInfo : toJson(levyExclInfo))
            .addObject("saveCallbackFuncName", hReq.getParameter("saveCallbackFuncName"))
            .addObject("savedCallbackFuncName", hReq.getParameter("savedCallbackFuncName"))
        ;
    }

    /**부과제외 대장를 등록한다.
     * @param levyExcl 부과제외 대장 정보
     * @return jsonView
     * <pre><code> {
     *     "saved": 등록되었으면 true, 그렇지 않으면 false
     * }</code></pre>
     */
    @Task
    @RequestMapping(name = "부과제외 대장 등록", value=METHOD_URL.createLevyExclusion)
    public ModelAndView createLevyExclusion(LevyExcl levyExcl) {
        String rtnMsg = levyExclService.createLevyExcl(levyExcl);

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

    /**부과제외 대장 정보를 수정한다.
     * @param levyExcl 부과제외 대장 정보
     * @return jsonView
     * <pre><code> {
     *     "saved": 수정되었으면 true, 그렇지 않으면 false
     * }</code></pre>
     */
    @Task
    @RequestMapping(name = "부과제외 대장 수정", value=METHOD_URL.updateLevyExclusion)
    public ModelAndView updateLevyExclusion(LevyExcl levyExcl) {
        String rtnMsg = levyExclService.updateLevyExcl(levyExcl);

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

    /**지정한 부과제외 ID에 해당하는 부과제외 대장를 제거한다.
     * @param levyExclID 부과제외 대장 아이디
     * @return jsonView
     * <pre><code> {
     *     "affected": 저장된 정보수
     *     "saved": 저장되었으면 true, 그렇지 않으면 false
     * }</code></pre>
     */
    @Task
    @RequestMapping(name = "부과제외 대장 삭제", value=METHOD_URL.removeLevyExclusion)
    public ModelAndView removeLevyExclusion(LevyExcl levyExcl) {
        String rtnMsg = "";

        // 부과제외(levyExclId) 단건 삭제
        if (isEmpty(levyExcl.getLevyExclIds())) {
            rtnMsg = levyExclService.removeLevyExcl(levyExcl);
        } else {
            // 부과제외 IDs 만큼 부과제외 삭제 반복..
            for (String levyExclId : levyExcl.getLevyExclIds()) {
                LevyExcl deltLevyExcl = new LevyExcl();
                deltLevyExcl.setLevyExclId(levyExclId);
                deltLevyExcl.setDelRsn(levyExcl.getDelRsn());

                // 부과제외 삭제 호출
                rtnMsg = levyExclService.removeLevyExcl(deltLevyExcl);
                if (!rtnMsg.contains("[S]"))                                    // 오류가 발생하였으면 종료..
                    break;
            }
        }

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