package com.zbkj.front.controller.bcx;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zbkj.common.exception.CrmebException;
import com.zbkj.common.request.PageParamRequest;
import com.zbkj.common.request.bcx.BcxFapiaoApplyRequest;
import com.zbkj.common.request.bcx.BcxWriteFapiaoRequest;
import com.zbkj.common.response.bcx.BcxFapiaoApplyResponse;
import com.zbkj.common.response.bcx.BcxWriteFapiaoImportResponse;
import com.zbkj.common.response.excel.BcxFapiaoWriteExcelDto;
import com.zbkj.common.result.CommonResult;
import com.zbkj.common.utils.ExportUtil;
import com.zbkj.service.service.bcx.BcxFapiaoApplyService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 发票管理 控制层
 */
@Slf4j
@Api(tags = "发票开具-控制器")
@RestController
@RequestMapping("/api/front/fapiao")
public class BcxFapiaoWriteController {

    @Autowired
    private BcxFapiaoApplyService bcxFapiaoApplyService;

    @ApiOperation(value = "开票方 发票查询-导出excel")
    @RequestMapping(value = "/writer/excel", method = {RequestMethod.POST})
    public void queryWriterPagedList(@RequestBody @Validated BcxFapiaoApplyRequest request, HttpServletResponse response) {
        //获取导出excel表格的数据列表
        List<BcxFapiaoWriteExcelDto> resultList = Collections.singletonList(new BcxFapiaoWriteExcelDto());
        PageParamRequest pageParamRequest = getExportPageRequest();
        List<BcxFapiaoApplyResponse> list = bcxFapiaoApplyService.queryWriterPagedList(request, pageParamRequest).getList();
        exportList(response, resultList, list);
    }

    @ApiOperation(value = "收票方 发票查询-导出excel")
    @RequestMapping(value = "/receiver/excel", method = {RequestMethod.POST})
    public void queryReceiverPagedList(@RequestBody @Validated BcxFapiaoApplyRequest request, HttpServletResponse response) {
        //获取导出excel表格的数据列表
        List<BcxFapiaoWriteExcelDto> resultList = Collections.singletonList(new BcxFapiaoWriteExcelDto());
        PageParamRequest pageParamRequest = getExportPageRequest();
        List<BcxFapiaoApplyResponse> list = bcxFapiaoApplyService.queryReceiverPagedList(request, pageParamRequest).getList();
        exportList(response, resultList, list);
    }

    private static PageParamRequest getExportPageRequest() {
        PageParamRequest pageParamRequest = new PageParamRequest();
        pageParamRequest.setPage(1);
        pageParamRequest.setLimit(65500);
        return pageParamRequest;
    }

    private void exportList(HttpServletResponse response, List<BcxFapiaoWriteExcelDto> resultList, List<BcxFapiaoApplyResponse> list) {
        if (CollectionUtil.isNotEmpty(list)) {
            //转导出对象
            resultList = list.stream().map(reportResponse -> {
                BcxFapiaoWriteExcelDto excelVo = new BcxFapiaoWriteExcelDto();
                BeanUtils.copyProperties(reportResponse, excelVo);
                return excelVo;
            }).collect(Collectors.toList());
        }
        ExportUtil<BcxFapiaoWriteExcelDto> exportUtil = new ExportUtil<>();
        exportUtil.export("发票申请单列表", resultList, response);
    }

    @ApiOperation(value = "批量开票-上传excel")
    @RequestMapping(value = "/write/upload", method = RequestMethod.POST)
    public CommonResult<List<BcxWriteFapiaoImportResponse>> file(@RequestParam(value = "file") MultipartFile file) {
        List<BcxWriteFapiaoImportResponse> resultList = new ArrayList<>();
        AnalysisEventListener<BcxWriteFapiaoRequest> listener = new AnalysisEventListener<BcxWriteFapiaoRequest>() {
            @Override
            public void invoke(BcxWriteFapiaoRequest record, AnalysisContext analysisContext) {
                Integer rowIndex = analysisContext.readRowHolder().getRowIndex();
                log.debug("解析第"+rowIndex+"行数据：{}", JSON.toJSONString(record));
                BcxWriteFapiaoImportResponse response = new BcxWriteFapiaoImportResponse();
                try {
                    response.setSuccess(true);
                    response.setApplyNo(record.getApplyNo());
                    response.setRowIndex(rowIndex);
                    if (!bcxFapiaoApplyService.writeFapiao(record)) {
                        response.setSuccess(false);
                        response.setMsg("处理失败，请检查数据是否正确，或联系管理员！");
                    }
                } catch (Exception e) {
                    response.setSuccess(false);
                    response.setMsg(e.getMessage());
                    log.error("单条处理失败" + JSONObject.toJSONString(response));
                }finally {
                    resultList.add(response);
                }
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                log.debug("全部解析完成");
            }
        };

        readExcel(file, listener);

        return CommonResult.success(resultList);
    }

    public void readExcel(MultipartFile file, AnalysisEventListener<BcxWriteFapiaoRequest> listener) {
        try {
            log.debug("发票excel解析开始");
            EasyExcel.read(file.getInputStream())
                    .autoCloseStream(false)
                    .autoTrim(true)
                    .sheet(0)
                    .head(BcxWriteFapiaoRequest.class)
                    .headRowNumber(1)
                    .registerReadListener(listener)
                    .doReadSync();
        } catch (IOException e) {
            log.error("读取excel失败", e);
            throw new CrmebException("上传失败，请检查excel格式");
        }
    }
}
