package com.iformall.controller.app;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor;
import com.github.pagehelper.PageInfo;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.domain.po.WxAppinfo;
import com.iformall.exception.MallinkException;
import com.iformall.service.WxAppinfoService;
import com.iformall.service.wechat.FmOpenService;
import com.iformall.utils.Constant;
import com.iformall.utils.MaUtil;
import com.iformall.utils.QRCodeUtils;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

@RestController
@RequestMapping("wxAppinfo")
public class WxAppinfoController extends BaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private boolean isFmOpen;

    @Autowired
    private String fmUploadDir;

    @Autowired
    private WxAppinfoService wxAppinfoService;

    @Autowired
    private FmOpenService openService;

    @ApiOperation("分页列表接口")
    @GetMapping("list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
    public ResultData list(@ModelAttribute WxAppinfo wxAppinfo, Integer pageNum, Integer pageSize) {
        logger.debug("[" + getIpAddr() + "] WxAppinfoController::list");
        if (null == wxAppinfo) wxAppinfo = new WxAppinfo();
        final PageInfo<WxAppinfo> page = wxAppinfoService.listAsPage(wxAppinfo, pageNum, pageSize);
        return new ResultData(page);
    }

    @ApiOperation("新增接口")
    @PostMapping("add")
    public ResultData add(@RequestBody WxAppinfo wxAppinfo) {
        logger.debug("[" + getIpAddr() + "] WxAppinfoController::add");
        //Assert.notNull(wxAppinfo.getName(), "角色名不能为空");
        //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名");
        wxAppinfoService.saveOrUpdate(wxAppinfo);
        return new ResultData();
    }

    @ApiOperation("根据id更新接口")
    @PostMapping("update")
    public ResultData update(@RequestBody WxAppinfo wxAppinfo) {
        logger.debug("[" + getIpAddr() + "] WxAppinfoController::update");
        wxAppinfoService.saveOrUpdate(wxAppinfo);
        return new ResultData();
    }

    @ApiOperation("根据id删除接口")
    @GetMapping("/del")
    @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true)
    public ResultData delete(Long id) {
        logger.debug("[" + getIpAddr() + "] WxAppinfoController::delete");
        wxAppinfoService.deleteById(id);
        return new ResultData(Result.SUCCESS, "删除成功", null);
    }

    @ApiOperation("根据id查询接口")
    @GetMapping("/findById")
    @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true)
    public ResultData findById(Long id) {
        logger.debug("[" + getIpAddr() + "] WxAppinfoController::findById");
        return new ResultData(Result.SUCCESS, "查询成功", wxAppinfoService.getById(id));
    }

    @ApiOperation(value = "下载二维码", produces="application/json;charset=UTF-8", notes = "参数{\"name\":\"String\",\"pageUrl\":\"String\", \"sceneParam\":\"二维码参数\", \"type\":0:有限二维码，1：无限二维码,\"withText\":int(0:不带字, 1:加一行字，2:加两行字),\"text1\":\"String\",\"text2\":\"String\"}")
    @PostMapping("/downQrCode")
    public void downQrCode(HttpServletRequest request, HttpServletResponse response, @RequestBody Map<String, Object> params) throws MallinkException {
        logger.debug("[" + getIpAddr() + "] WxAppinfoController::downQrCode");
        String name = (String) params.get("name");
        String pageUrl = (String) params.get("pageUrl");
        String sceneParam = (String) params.get("sceneParam");
        int type = 0;
        try {
            type = (int) params.get("type");
        } catch (Exception e) {
            type = 0;
        }

        int withText = 0;
        try {
            withText = (int) params.get("withText");
        } catch (Exception e) {
            withText = 0;
        }
        String text1 = (String) params.get("text1");
        String text2 = (String) params.get("text2");
        if (StringUtils.isBlank(pageUrl)) {
            throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "pageUrl不能为空");
        }
        try {
            exportQrcode(request, response,
                    getTenantId(), type, pageUrl, sceneParam,
                    withText, text1, text2,
                    name);
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw new MallinkException(Result.ERROR, "下载异常");
        }
    }

    private void exportQrcode(HttpServletRequest request, HttpServletResponse response,
                             String tenantId, int type, String pageUrl, String sceneParam,
                             int withText, String text1, String text2,
                              String name) {
        // type 0 有限二维码, 1 无限制二维码
        // withText 0 不带字 1. 带下面的字，2 带下面的两行字
        WxAppinfo appinfo = wxAppinfoService.getCAppInfo(tenantId);
        boolean autoColor = false;
        boolean isHyaline = true;
        WxMaCodeLineColor color = new WxMaCodeLineColor("0", "0", "0");

        WxMaService wxMaService;
        if(isFmOpen) {
            wxMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appinfo.getAppId());
        } else {
            wxMaService = MaUtil.getWeappService(appinfo);
        }

        String pathStr = "";
        if (StringUtils.isNotBlank(sceneParam)) {
            pathStr = pageUrl + "?scene="+sceneParam;
        } else {
            pathStr = pageUrl;
        }


        String filepath = fmUploadDir;
        String fileName = name + ".png";
        String destPath1 = filepath + "1_" + fileName;
        String destPath = filepath + fileName;

        File dest = new File(destPath);
        File pDest = dest.getParentFile();
        if (!pDest.exists()) {
            pDest.mkdirs();
        }
        try {
            if(type == 0) {
                final File codeFile = wxMaService.getQrcodeService().createQrcode(pathStr, QRCodeUtils.QR_WIDTH);
                if (withText == 1) {
                    File dest1 = new File(destPath1);
                    org.apache.commons.io.FileUtils.copyFile(codeFile, dest1);
                    QRCodeUtils.graphicsGeneration(dest1, dest, text1);
                    org.apache.commons.io.FileUtils.forceDelete(dest1);
                } else if (withText == 2) {
                    File dest1 = new File(destPath1);
                    org.apache.commons.io.FileUtils.copyFile(codeFile, dest1);
                    QRCodeUtils.graphicsGeneration2(dest1, dest, text1, text2);
                    org.apache.commons.io.FileUtils.forceDelete(dest1);
                } else {
                    org.apache.commons.io.FileUtils.copyFile(codeFile, dest);
                }
                org.apache.commons.io.FileUtils.forceDelete(codeFile);
            } else {
                final File codeFile = wxMaService.getQrcodeService().createWxaCodeUnlimit(sceneParam, pageUrl, QRCodeUtils.QR_WIDTH, autoColor, color, isHyaline);
                if (withText == 1) {
                    File dest1 = new File(destPath1);
                    org.apache.commons.io.FileUtils.copyFile(codeFile, dest1);
                    QRCodeUtils.graphicsGeneration(dest1, dest, text1);
                    org.apache.commons.io.FileUtils.forceDelete(dest1);
                } else if (withText == 2) {
                    File dest1 = new File(destPath1);
                    org.apache.commons.io.FileUtils.copyFile(codeFile, dest1);
                    QRCodeUtils.graphicsGeneration2(dest1, dest, text1, text2);
                    org.apache.commons.io.FileUtils.forceDelete(dest1);
                } else {
                    org.apache.commons.io.FileUtils.copyFile(codeFile, dest);
                }
                org.apache.commons.io.FileUtils.forceDelete(codeFile);
            }

        } catch (WxErrorException e) {
            logger.error(e.getMessage());
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

        try {
            downFile(destPath, fileName, response, request);
            org.apache.commons.io.FileUtils.forceDelete(dest);
        } catch (Exception e) {
            logger.error(e.getMessage());
        }

    }

    private void downFile(String filePath, String filename, HttpServletResponse response, HttpServletRequest req) throws IOException {
        try {
            response.reset();
            response.setContentType("application/octet-stream");
            String agent = req.getHeader("user-agent");
            if (agent.contains("Firefox")) {
                response.setHeader("Content-disposition",
                        "attachment; filename="
                                + new String(filename.getBytes("GB2312"),"ISO-8859-1"));
            } else {
                response.setHeader("Content-disposition",
                        "attachment; filename="
                                + java.net.URLEncoder.encode(filename,"UTF-8"));
            }
            // 循环取出流中的数据
            byte[] b = new byte[1024];
            int len;
            InputStream inStream = new FileInputStream(filePath);
            while ((len = inStream.read(b)) > 0)
                response.getOutputStream().write(b, 0, len);
            inStream.close();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }


}
