package cokr.xit.fims.chongno;

import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import cokr.xit.base.file.FileInfo;
import cokr.xit.base.file.service.bean.FileBean;
import cokr.xit.fims.base.FimsUser;
import cokr.xit.fims.cmmn.FimsPrintOption;
import cokr.xit.fims.crdn.Crdn;
import cokr.xit.fims.crdn.service.CrdnService;
import cokr.xit.fims.sndb.SndbQuery;
import cokr.xit.fims.sndb.service.SndngDtlService;
import cokr.xit.fims.sprt.SprtQuery;
import cokr.xit.fims.sprt.dao.IntegrationSearchMapper;
import cokr.xit.fims.sprt.service.bean.MediaBean;
import cokr.xit.foundation.data.DataFormat;
import cokr.xit.foundation.data.DataObject;
import cokr.xit.foundation.web.AbstractController;

@Controller
@RequestMapping("/preview")
public class JasperController extends AbstractController {
    @Resource(name="crdnService")
	private CrdnService crdnService;
    /**발송 상세 서비스*/
    @Resource(name="sndngDtlService")
    private SndngDtlService sndngDtlService;
    @Resource(name="integrationSearchMapper")
    private IntegrationSearchMapper integrationSearchMapper;
    @Resource(name="fileBean")
    private FileBean fileBean;
    @Resource(name="mediaBean")
    private MediaBean mediaBean;

    @RequestMapping(name="계도장 미리보기", value="/warning.do")
    public ModelAndView previewWarning(SndbQuery req) {
        List<DataObject> result = sndngDtlService.getSndngDtlList(req.setFetchSize(0));
    	List<String> crdnIdList = result.stream().map(row -> row.string("CRDN_ID")).distinct().toList();
        String[] crdnIDs = crdnIdList.toArray(new String[crdnIdList.size()]);
        Map<String, DataObject> crdns = getCrdnList(new SndbQuery().setCrdnIds(crdnIDs)).stream()
        	.collect(Collectors.toMap(row -> row.string("CRDN_ID"), row -> row));
        result.forEach(row -> {
        	String crdnId = row.string("CRDN_ID");
        	DataObject crdn = crdns.get(crdnId);
        	if (crdn == null) return;

    		row.set("CRDN_YMD_TM", DataFormat.yyyy_mm_dd(crdn.get("CRDN_YMD")) + " " + DataFormat.hh_mm_ss(crdn.get("CRDN_TM")))
    		   .set("RTPYR_ADDR", crdn.get("RTPYR_ADDR"))
    		   .set("RTPYR_DTL_ADDR", crdn.get("RTPYR_DTL_ADDR"))
    		   .set("RTPYR_ZIP", crdn.get("RTPYR_ZIP"))
    		   .set("RTPYR_NM", crdn.get("RTPYR_NM"))
    		   .set("RTPYR_NM", crdn.get("RTPYR_NM"))
    		   .set("VLTN_ARTCL", crdn.get("VLTN_ARTCL"))
    		   .set("VLTN_LAW_NM", crdn.get("VLTN_LAW_NM"));
        });

		Map<String, List<FileInfo>> crdnFiles = fileBean.getFilesOf(Crdn.INF_TYPE, crdnIDs).stream()
        	.collect(Collectors.groupingBy(row -> row.getInfoKey()));
        List<InputStream> inputStreams = result.stream()
            	.flatMap(crdn -> {
    	        	List<FileInfo> files = crdnFiles.get(crdn.string("CRDN_ID"));
    	        	List<InputStream> inputs = isEmpty(files) ? Collections.emptyList() :
    	        		files.stream()
    	        			 .map(FileInfo::getInputStream)
    	        			 .toList();

    	        	for (int i = 0; i < Math.min(4, inputs.size()); ++i) {
    					crdn.set("VLTN_IMG" + i, inputs.get(i));
    	        	}
    	        	return inputs.stream();
    	        })
    	        .toList();

        String today = dateFormats.format("yyyyMMdd", System.currentTimeMillis());
        FimsUser user = (FimsUser)currentUser().getUser();
        DataObject params = new DataObject()
        	.set("thisYear", today.substring(0, 4))
        	.set("thisMonth", today.substring(4, 6))
        	.set("thisDay", today.substring(6))
        	.set("managerName", user.getName())
        	.set("managerPhoneNo", user.getPhoneNo())
        	.set("managerEmail", user.getEmailAddress());

        return new ModelAndView("jasperView")
        	.addObject("jasper", "warning.jasper")
        	.addObject("params", params)
        	.addObject("dataMap", result)
        	.addObject("filename", "warning.pdf")
        	.addObject("closables", inputStreams);
    }

    private List<DataObject> getCrdnList(SndbQuery req) {
    	String[] crdnIds = req.getCrdnIds();
    	if (isEmpty(crdnIds)) {
	        List<DataObject> trgtDtls = sndngDtlService.getSndngTrgtDtlIds(req);
	        crdnIds = trgtDtls.stream()
	        	.map(row -> row.string("CRDN_ID"))
	        	.toList()
	        	.toArray(new String[trgtDtls.size()]);
    	}

    	return integrationSearchMapper.selectIntegrationDataList(new SprtQuery().setCrdnIds(crdnIds));
    }

    @RequestMapping(name="사전통지서 미리보기", value="/prenotice.do")
    public ModelAndView previewPrenotice(SndbQuery req) {
    	List<DataObject> dtlList = sndngDtlService.getDetailList(List.of(req.getSndngId()));
    	String[] crdnIds = dtlList.stream().map(row -> row.string("CRDN_ID")).toList().toArray(new String[dtlList.size()]);
        Map<String, List<FileInfo>> crdnFiles = fileBean.getFilesOf(Crdn.INF_TYPE, crdnIds).stream()
        	.collect(Collectors.groupingBy(row -> row.getInfoKey()));
        setBankAccounts(dtlList);

        String today = dateFormats.format("yyyyMMdd", System.currentTimeMillis()),
         	   year = today.substring(0, 4),
         	   month = today.substring(4, 6),
         	   day = today.substring(6),
         	   userName = "박재현",
        	   userPhoneNo = "02-2148-1857",
        	   userEmail = "poe307@mail.jongno.go.kr";
        List<InputStream> inputStreams = dtlList.stream()
        	.flatMap(dtl -> {
    			String taxNo = dtl.string("TAX_NO");
        		dtl.set("CRDN_YMD_TM", DataFormat.yyyy_mm_dd(dtl.get("CRDN_YMD")) + " " + DataFormat.hh_mm_ss(dtl.get("CRDN_TM")))
        			.set("ADVNTCE_DUDT_YMD", DataFormat.yyyy_mm_dd(dtl.get("ADVNTCE_DUDT_YMD")))
        			.set("issueYear", year).set("issueMonth", month).set("issueDay", day)
        			.set("managerName", userName).set("managerPhoneNo", userPhoneNo).set("managerEmail", userEmail)
        			.set("napbuYm", isEmpty(taxNo) ? null : taxNo.substring(15, 22))
	        	   ;

	        	List<FileInfo> files = crdnFiles.get(dtl.string("CRDN_ID"));
	        	List<InputStream> inputs = isEmpty(files) ? Collections.emptyList() :
	        		files.stream()
	        			 .map(FileInfo::getInputStream)
	        			 .toList();

	        	for (int i = 0; i < Math.min(4, inputs.size()); ++i) {
					dtl.set("VLTN_IMG" + i, inputs.get(i));
	        	}
	        	return inputs.stream();
	        })
	        .toList();

        return new ModelAndView("jasperView")
        	.addObject("jasper", "/prenotice-a4.jasper")
        	.addObject("dataMap", dtlList)
        	.addObject("filename", "prenotice.pdf")
        	.addObject("closables", inputStreams);
    }

    private void setBankAccounts(List<DataObject> list) {
    	if (isEmpty(list)) return;

    	for (DataObject row: list) {
    		for (int i = 0; i < 20; ++i) {
    			String suffix = i < 1 ? "" : Integer.toString(i + 1),
    				   bankKey = "BANK_NM" + suffix,
     				   bankField = switch (row.string(bankKey)) {
     				   case "신한" -> "SAccountNo";
     				   case "우리" -> "WAccountNo";
     				   case "하나" -> "HAccountNo";
     				   case "국민" -> "KAccountNo";
     				   case "기업" -> "IAccountNo";
     				   case "우체국" -> "PAccountNo";
     				   case "씨티" -> "CAccountNo";
     				   case "농협" -> "NAccountNo";
     				   case "수협" -> "FAccountNo";
     				   case "카카오" -> "OAccountNo";
     				   case "K뱅크" -> "QAccountNo";
     				   case "토스뱅크" -> "TAccountNo";
     				   default -> null;
     				   };
     			if (bankField == null) continue;

  	    		String accountKey = "VR_ACTNO" + suffix,
    				   accountNo = row.string(accountKey);

    			row.remove(bankKey);
    			row.remove(accountKey);
    			row.put(bankField, accountNo);
    		}
    	}
    }

    @RequestMapping(name="고지서 미리보기", value="/notice.do")
    public ModelAndView previewNotice(SndbQuery req, FimsPrintOption printOption) {
    	List<DataObject> dtlList = sndngDtlService.getDetailList(List.of(req.getSndngId())); //getCrdnList(req);
    	setBankAccounts(dtlList);

        String today = dateFormats.format("yyyyMMdd", System.currentTimeMillis()),
          	   year = today.substring(0, 4),
          	   month = today.substring(4, 6),
          	   day = today.substring(6),
		  	   userName = "박재현",
		 	   userPhoneNo = "02-2148-1857",
		 	   userEmail = "poe307@mail.jongno.go.kr";
        dtlList.forEach(dtl -> {
			String taxNo = dtl.string("TAX_NO");

    		dtl.set("CRDN_YMD_TM", DataFormat.yyyy_mm_dd(dtl.get("CRDN_YMD")) + " " + DataFormat.hh_mm_ss(dtl.get("CRDN_TM")))
    			.set("DUDT_YMD", DataFormat.yyyy_mm_dd(dtl.get("DUDT_YMD")))
    			.set("DUDT_AFTR_YMD", DataFormat.yyyy_mm_dd(dtl.get("DUDT_AFTR_YMD")))
    			.set("issueYear", year).set("issueMonth", month).set("issueDay", day)
    			.set("napbuYm", isEmpty(taxNo) ? null : taxNo.substring(15, 22))
    			.set("managerName", userName).set("managerPhoneNo", userPhoneNo).set("managerEmail", userEmail);
        });
        DataObject params = new DataObject()
        	.set("thisYear", year)
        	.set("thisMonth", month)
        	.set("thisDay", day)
        	.set("managerName", userName)
        	.set("managerPhoneNo", userPhoneNo)
        	.set("managerEmail", userEmail);

        String jasper = switch (printOption.getPaperSeCd()) {
        case "01" -> "/notice-a4.jasper";
        case "02" -> "/notice-letter.jasper";
        default -> throw new IllegalArgumentException("paperSeCd: " + printOption.getPaperSeCd());
        };
        return new ModelAndView("jasperView")
        	.addObject("jasper", jasper)
        	.addObject("params", params)
        	.addObject("dataMap", dtlList)
        	.addObject("filename", "prenotice.pdf");
    }
}