package com.dxhy.sign.controller;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.fastjson.JSONObject;
import com.dxhy.auth.client.annotation.IgnoreClientToken;
import com.dxhy.auth.client.annotation.IgnoreUserToken;
import com.dxhy.common.aspect.SysLog;
import com.dxhy.common.constant.CommonConstants;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.controller.AbstractController;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.FplxEnum;
import com.dxhy.common.util.FileUtils;
import com.dxhy.common.util.InvoiceUtil;
import com.dxhy.common.util.StringHelper;
import com.dxhy.common.util.ZipUtil;
import com.dxhy.common.utils.R;
import com.dxhy.common.vo.Business;
import com.dxhy.common.vo.UserInfo;
import com.dxhy.oss.model.FileModel;
import com.dxhy.oss.service.FileService;
import com.dxhy.sign.entity.TDxInvoiceImg;
import com.dxhy.sign.model.ElecInvoiceRespVO;
import com.dxhy.sign.model.ElecQueryReqVO;
import com.dxhy.sign.service.elec.SignElecInvoiceService;
import com.dxhy.sign.service.elec.SignInvoiceImgService;
import com.dxhy.sign.util.DateTimeHelper;
import com.dxhy.sign.util.ZipUtils;

import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author peipei.li
 * @date 2019-04-29 电票管理相关入口
 */
@SuppressWarnings({"AlibabaUndefineMagicConstant", "AlibabaMethodTooLong"})
@RestController
@RequestMapping("elec")

@Slf4j
public class SignElecInvoiceController extends AbstractController {

    @Resource
    private SignElecInvoiceService signElecInvoiceService;
    @Resource
    private FileService fileService;

    @Value("${ftp.connection.size}")
    private String size;
    /**
     * 上传时本地文件暂存路径
     */
    @Value("${ftp.connection.tempPath}")
    private String tempPath;
    /**
     * 上传时本地文件存放路径
     */
    @Value("${ftp.connection.depositPath}")
    private String depositPath;

    @Resource
    private SignInvoiceImgService signInvoiceImgService;

    /**
     * 电票查询
     *
     * @param reqVO
     *            请求参数
     * @return 返回结果
     */
    @RequestMapping("list/listElecQuery")
    @SysLog("电票查询")
    public ResponseEntity<R> listElecQuery(@RequestBody ElecQueryReqVO reqVO) {
        try {
            reqVO.setUserInfo(getUserInfo());
            return ResponseEntity.ok(R.ok().put("data", signElecInvoiceService.listPageElecInvoice(reqVO)));
        } catch (Exception e) {
            log.error("", e);
            return ResponseEntity.ok(R.error(CommonConstants.MSG_ERR_DEFAULT));
        }
    }

    /**
     * 获取电票图片
     *
     * @param response
     *            请求参数
     * @throws Exception
     *             异常
     */
    @RequestMapping("list/getImg")
    @SysLog("查看图片")
    public ResponseEntity<R> getImg(@RequestBody Map<String, String> pramsMap, HttpServletResponse response)
        throws Exception {
        if (StringHelper.isBlank(pramsMap.get("uuid"))) {
            return ResponseEntity.ok(R.error("请检查参数！"));
        }
        ServletOutputStream out = null;
        FileInputStream ips = null;
        String localPath = fileService.getLocalPathDefault() + "img/" + getUserName() + "/";
        String imgPath = signElecInvoiceService.getImgByUuid(pramsMap.get("uuid"), getUserInfo(), localPath);
        // 获取图片存放路径
        if (StringHelper.isBlank(imgPath)) {
            return ResponseEntity.ok(R.error("该发票无图片！"));
        }
        File imgFile = new File(imgPath);
        try {
            ips = new FileInputStream(imgFile);
            response.setContentType(MediaType.IMAGE_JPEG_VALUE);
            out = response.getOutputStream();
            // 读取文件流
            int len;
            byte[] buffer = new byte[1024 * 10];
            while ((len = ips.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 删除临时文件
            // 清空临时文件里面的文件
            FileUtils.deleteDir(new File(localPath));
            if (out != null) {
                out.close();
            }
            if (ips != null) {
                ips.close();
            }
        }
        return null;
    }

    @RequestMapping("/getFile")
    @ResponseBody
    @SysLog("获取文件流信息")
    public Object getImg(@RequestBody Map<String, String> pramsMap) {
        if (StringHelper.isBlank(pramsMap.get("scanId"))) {
            return ResponseEntity.ok(R.error("请检查参数！"));
        }
        if (StringHelper.isBlank(pramsMap.get("imgOrFile"))) {
            return ResponseEntity.ok(R.error("请检查参数！"));
        }
        try {
            String localPath = fileService.getLocalPathDefault() + "file/" + getUserName() + "/";
            return signElecInvoiceService.getFileByScanId(pramsMap.get("scanId"), pramsMap.get("imgOrFile"),
                getUserInfo(), localPath);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.ok(R.error(CommonConstants.MSG_ERR_DEFAULT));
        }
    }

    /**
     * 上传发票文件
     *
     * @param file
     *            文件
     * @return 返回结果
     */
    @PostMapping("edit/uploadFile")
    @SysLog("上传电子发票")
    public ResponseEntity<R> uploadFile(MultipartFile file, String businessCode) {
        try {
            log.debug("businessCode =--------------- " + businessCode);
            // 业务单元信息设置
            UserInfo userInfo = getUserInfo();
            String businessName = "";
            if (StringUtils.isNoneBlank(businessCode) && !"99".equals(businessCode)) {
                List<Business> businessList = userInfo.getBusiness();
                for (Business business : businessList) {
                    if (business.getBusinessCode().equals(businessCode)) {
                        businessName = business.getBusinessName();
                    }
                }
            } else {
                businessCode = "";
            }
            boolean checkFileSize = FileUtils.checkFileSize(file.getSize(), Integer.parseInt(size), "M");
            if (!checkFileSize) {
                return ResponseEntity.ok(R.error("上传文件大于 " + size + "M"));
            }
            String filename = file.getOriginalFilename();
            String prefix = filename != null ? filename.substring(filename.lastIndexOf(".") + 1) : null;
            if (!"zip".equals(prefix) && !"pdf".equals(prefix) && !"ZIP".equals(prefix) && !"PDF".equals(prefix)
                && !"ofd".equals(prefix) && !"OFD".equals(prefix)) {
                return ResponseEntity.ok(R.error("请上传pdf、ofd文件或者pdf、ofd的压缩文件(.zip)！"));
            }

            // 文件名称
            String fileName = signElecInvoiceService.getOriginalFilename(file.getOriginalFilename());
            // 上传文件重新命名
            String pdfFileName = userInfo.getUsername() + "_" + DateTimeHelper.formatNowDate("yyyyMMddHHmmss")
                + fileName.substring(fileName.indexOf("."));
            // 创建临时存储文件夹
            String tempPathPdf =
                tempPath + userInfo.getUsername() + "_" + DateTimeHelper.formatNowDate("yyyyMMddHHmmss") + "/";
            signElecInvoiceService.createFileDir(tempPathPdf);
            File newFile = new File(tempPathPdf + pdfFileName);
            try {
                file.transferTo(newFile.getAbsoluteFile());
                if (fileName.contains("zip") || fileName.contains("ZIP")) {
                    // 若用户上传的是zip压缩文件,对文件进行解压
                    ZipUtil.unzip(tempPathPdf + pdfFileName);
                    // 对上传的文件进行移动保存
                    FileUtil.move(newFile, new File(depositPath), true);
                } else if (fileName.contains("ofd") || fileName.contains("OFD")) {
                    // 对用ofd上传，压缩ofd文件，然后保存
                    ZipUtil.zip(newFile, Boolean.FALSE);
                    List<File> zipFiles = FileUtils.findFile(tempPathPdf, "zip");
                    for (File zipFile : zipFiles) {
                        // 对上传的文件进行移动保存
                        FileUtil.move(zipFile, new File(depositPath), true);
                    }
                } else {
                    // 对用pdf上传，压缩pdf文件，然后保存
                    ZipUtil.zip(newFile, Boolean.FALSE);
                    List<File> zipFiles = FileUtils.findFile(tempPathPdf, "zip");
                    for (File zipFile : zipFiles) {
                        // 对上传的文件进行移动保存
                        FileUtil.move(zipFile, new File(depositPath), true);
                    }
                }
                // 获取临时文件夹里的所有pdf文件
                List<File> files = null;
                if (fileName.contains("pdf") || fileName.contains("zip") || fileName.contains("PDF")
                    || fileName.contains("ZIP") || fileName.contains("ofd") || fileName.contains("OFD")) {
                    files = FileUtils.findFile(tempPathPdf, "");
                }
                List<File> pdfFile = new ArrayList<>();
                List<File> ofdFile = new ArrayList<>();
                if (files != null && files.size() > 0) {
                    for (File fi : files) {
                        String name = fi.getName();
                        if (!name.contains("pdf") && !name.contains("PDF") && !name.contains("ZIP")
                            && !name.contains("zip") && !name.contains("ofd") && !name.contains("OFD")) {
                            return ResponseEntity.ok(R.error("请上传pdf、ofd文件或者pdf、ofd的压缩文件(.zip)！"));
                        }
                        if (name.contains("pdf") || name.contains("PDF")) {
                            pdfFile.add(fi);
                        }
                        if (name.contains("ofd") || name.contains("OFD")) {
                            ofdFile.add(fi);
                        }
                    }

                    JSONObject saveUploadElecFile = signElecInvoiceService.saveUploadElecFile(pdfFile, ofdFile,
                        userInfo, pdfFileName, tempPathPdf, businessName, businessCode);
                    return ResponseEntity.ok(R.ok().put("data", saveUploadElecFile));
                } else {
                    return ResponseEntity.ok(R.error("请上传pdf、ofd文件或者pdf、ofd的压缩文件(.zip)！"));
                }
            } catch (Exception e) {
                e.printStackTrace();
                return ResponseEntity.ok(R.error("请上传pdf、ofd文件或者pdf、ofd的压缩文件(.zip)！"));
            }

        } catch (Exception e) {
            e.printStackTrace();
            log.error("", e);
            return ResponseEntity.ok(R.error("上传失败，请查看上传文件是否正确。"));
        }
    }

    /**
     * 手工录入电子发票
     *
     * @param reqVO
     *            请求参数
     * @return 返回结果
     */
    @PostMapping("edit/saveManualElec")
    @SysLog("手工录入电子发票")
    public ResponseEntity<R> saveManualElec(@RequestBody ElecInvoiceRespVO reqVO) {
        try {
//            if (StringHelper.isBlank(reqVO.getInvoiceCode())) {
//                return ResponseEntity.ok(R.error("发票代码不能为空！"));
//            }
            if (StringHelper.isBlank(reqVO.getInvoiceNo())) {
                return ResponseEntity.ok(R.error("发票号码不能为空！"));
            }
            InvoiceUtil iu = new InvoiceUtil(reqVO.getInvoiceCode());
            if (!(FplxEnum.QDZZP.getFplxDm().equals(reqVO.getInvoiceType()) || FplxEnum.QDPP.getFplxDm().equals(reqVO.getInvoiceType()))) {
                reqVO.setInvoiceType(iu.getFplxdm());
                if (StringHelper.isBlank(reqVO.getInvoiceCode())) {
                    return ResponseEntity.ok(R.error("发票代码不能为空！"));
                }
            }
            if (FplxEnum.QDZZP.getFplxDm().equals(reqVO.getInvoiceType())
                    || FplxEnum.QDPP.getFplxDm().equals(reqVO.getInvoiceType())) {
                reqVO.setInvoiceAmount(reqVO.getTotalAmount());
            }
            if (FplxEnum.ZP.getFplxDm().equals(reqVO.getInvoiceType())
                || FplxEnum.JDC.getFplxDm().equals(reqVO.getInvoiceType())
                || FplxEnum.DZZP.getFplxDm().equals(reqVO.getInvoiceType())
                || FplxEnum.QDZZP.getFplxDm().equals(reqVO.getInvoiceType())
                || FplxEnum.QDPP.getFplxDm().equals(reqVO.getInvoiceType())) {
                if (StringHelper.isBlank(reqVO.getInvoiceAmount())) {
                    return ResponseEntity.ok(R.error("金额不能为空！"));
                }
            } else {
                if (StringHelper.isBlank(reqVO.getCheckCode())) {
                    return ResponseEntity.ok(R.error("校验码不能为空！"));
                }
            }
            if (reqVO.getInvoiceDate() == null) {
                return ResponseEntity.ok(R.error("开票日期不能为空！"));
            }

            // 业务单元参数设置
            UserInfo userInfo = getUserInfo();
            String businessName = "";
            String businessCode = reqVO.getBusinessCode();
            if (StringUtils.isNoneBlank(businessCode) && !"99".equals(businessCode)) {
                List<Business> businessList = userInfo.getBusiness();
                for (Business business : businessList) {
                    if (business.getBusinessCode().equals(reqVO.getBusinessCode())) {
                        businessName = business.getBusinessName();
                    }
                }
            } else {
                businessCode = "";
            }
            reqVO.setBusinessCode(businessCode);
            reqVO.setBusinessName(businessName);
            reqVO.setCompany(userInfo.getCompany());
            return ResponseEntity.ok(R.ok().put("data", signElecInvoiceService.saveManualElec(reqVO, userInfo)));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("", e);
            return ResponseEntity.ok(R.error(CommonConstants.MSG_ERR_DEFAULT));
        }
    }

    @RequestMapping("/deleteElec")
    @SysLog("删除签收失败发票")
    public ResponseEntity<R> deleteElec(@RequestBody Map<String, String> pramsMap) {
        log.info("删除签收失败发票参数{}",pramsMap);
        try {
            // 删除 扫描表信息
            boolean deleteElec = signElecInvoiceService.deleteElec(pramsMap.get("scanId"), getUserInfo().getDbName());
            if (deleteElec) {
                return ResponseEntity.ok(R.ok().put("data", "删除成功！"));
            } else {
                return ResponseEntity.ok(R.error("删除失败！"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("", e);
            return ResponseEntity.ok(R.error(CommonConstants.MSG_ERR_DEFAULT));
        }
    }

    @RequestMapping("/deleteElecByID")
    @SysLog("删除签收失败发票")
    public ResponseEntity<R> deleteElecByID(@RequestBody Map<String, String> pramsMap) {
        try {
            // 删除 扫描表信息
            boolean deleteElec = signElecInvoiceService.deleteElecByID(pramsMap.get("id"), getUserInfo().getDbName());
            if (deleteElec) {
                return ResponseEntity.ok(R.ok().put("data", "删除成功！"));
            } else {
                return ResponseEntity.ok(R.error("删除失败！"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("", e);
            return ResponseEntity.ok(R.error(CommonConstants.MSG_ERR_DEFAULT));
        }
    }

    @ResponseBody
    @RequestMapping(value = "/updownImg")
    @IgnoreClientToken
    @IgnoreUserToken
    public void getImg(HttpServletRequest request, String scanId, HttpServletResponse response) {
        TDxInvoiceImg img;
        String downLondFile = "";
        try {

            DynamicContextHolder.push("business" + DbConstant.BUSINESS_READ);
            img = signInvoiceImgService.selectByUuid(scanId);

            if (null != img) {
                String[] fileAccount = null;
                if (img.getImagePath() != null) {
                    fileAccount = img.getImagePath().split("/");
                }
                String name = fileAccount[fileAccount.length - 1];
                downLondFile =
                    fileService.getLocalPathDefault() + "img/" + new SimpleDateFormat("yyyyMMdd").format(new Date())
                        + "/" + new File(img.getImagePath()).getName();
                FileModel fileModel = fileService.downFile(img.getImagePath(), downLondFile);
                byte[] zipFile;

                if (name.contains(".zip")) {
                    zipFile = ZipUtils.readZipFile(fileModel.getFilePath());
                } else {

                    zipFile = ZipUtils.readInputStream(new FileInputStream(new File(fileModel.getFilePath())));
                }
                // 从网盘下载照片的流
                InputStream in = new ByteArrayInputStream(zipFile);

                // 声明输出流，但是要从HttpServletResponse中获取才管用
                BufferedOutputStream bout = new BufferedOutputStream(response.getOutputStream());
                // 从输入流到输出流
                byte[] b = new byte[1024];
                int len = in.read(b);
                while (len > 0) {
                    bout.write(b, 0, len);
                    len = in.read(b);
                }

            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (org.apache.commons.lang3.StringUtils.isNotBlank(downLondFile)) {
                    String path = new File(downLondFile).getParent();
                    cn.hutool.core.io.FileUtil.del(new File(path));
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
