package com.iformall.controller.rent;

import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.PageInfo;
import com.iformall.annotation.SystemControllerLog;
import com.iformall.common.ErrorCode;
import com.iformall.common.Result;
import com.iformall.common.ResultData;
import com.iformall.controller.base.BaseController;
import com.iformall.controller.mem.BillDailyAsyncTask;
import com.iformall.domain.po.MallUserInfo;
import com.iformall.domain.po.WxBillDaily;
import com.iformall.enums.EnumBillDailyBuildWay;
import com.iformall.exception.MallinkException;
import com.iformall.service.WxBillDailyService;
import com.iformall.utils.Constant;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author gongbiao
 */
@RestController
@RequestMapping("wxBillDaily")
public class WxBillDailyController extends BaseController {

    @Autowired
    private String fmUploadDir;

    @Autowired
    private WxBillDailyService wxBillDailyService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    private BillDailyAsyncTask billDailyAsyncTask;

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @GetMapping("list")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)})
    @SystemControllerLog(description = "日常账单-列表")
    public ResultData list(@ModelAttribute WxBillDaily wxBillDaily, Integer pageNum, Integer pageSize) {
        logger.debug("[" + getIpAddr() + "] WxBillDailyController::list");
        if (null == wxBillDaily) {
            wxBillDaily = new WxBillDaily();
        }
        wxBillDaily.setTenantId(getTenantId());
        final PageInfo<WxBillDaily> page = wxBillDailyService.listAsPage(wxBillDaily, pageNum, pageSize);
        return new ResultData(page);
    }

    @PostMapping("add")
    @SystemControllerLog(description = "日常账单-新增")
    public ResultData add(@RequestBody WxBillDaily wxBillDaily) {
        logger.debug("[" + getIpAddr() + "] WxBillDailyController::add");
        MallUserInfo user = getUser();
        wxBillDaily.setTenantId(user.getTenantId());
        wxBillDaily.setUserId(user.getId());
        wxBillDaily.setBuildWay(EnumBillDailyBuildWay.HAND.getCode());
        return wxBillDailyService.saveOrUpdate(wxBillDaily, user);
    }

    @PostMapping("update")
    @SystemControllerLog(description = "日常账单-更新")
    public ResultData update(@RequestBody WxBillDaily wxBillDaily) {
        logger.debug("[" + getIpAddr() + "] WxBillDailyController::update");
        MallUserInfo user = getUser();
        wxBillDaily.setUserId(user.getId());
        return wxBillDailyService.saveOrUpdate(wxBillDaily, user);
    }

    @GetMapping("/del")
    @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true)
    @SystemControllerLog(description = "日常账单-删除")
    public ResultData delete(Long id) {
        logger.debug("[" + getIpAddr() + "] WxBillDailyController::delete");
        wxBillDailyService.deleteById(id);
        return new ResultData(Result.SUCCESS, "删除成功", null);
    }

    @GetMapping("/findById")
    @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true)
    @SystemControllerLog(description = "日常账单-id查找")
    public ResultData findById(Long id) {
        logger.debug("[" + getIpAddr() + "] WxBillDailyController::findById");
        return new ResultData(Result.SUCCESS, "查询成功", wxBillDailyService.getById(id));
    }

    @GetMapping("/updatePaid")
    @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true)
    @SystemControllerLog(description = "日常账单-支付更新")
    public ResultData updatePaid(Long id) {
        logger.debug("[" + getIpAddr() + "] WxBillDailyController::updatePaid");
        return wxBillDailyService.updatePaid(id);
    }

    @RequestMapping("/exportTemplate")
    @SystemControllerLog(description = "日常账单-导出模板")
    public void exportTemplate(HttpServletRequest request, HttpServletResponse response) {
        logger.debug("[" + getIpAddr() + "] wxBillDailyService::exportTemplate");
        wxBillDailyService.exportTemplate(request, response, getTenantId());

    }

    @PostMapping(value = "/importTemplate", consumes = "multipart/*")
    @SystemControllerLog(description = "日常账单-导入数据")
    public ResultData importTemplate(@RequestParam("file") MultipartFile mFile) {
        logger.debug("[" + getIpAddr() + "] wxBillDailyService::importTemplate");
        if (mFile.isEmpty()) {
            throw new MallinkException(Result.ERROR, "上传文件不能为空");
        }
        //得到当前用户ID
        final MallUserInfo user = getUser();
        String userId = "bill_daily_" + user.getId();
        String importKey = Constant.importMemPrev + userId;
        final String tenantId = getTenantId();

        //查询当前用户得到的值是否为空，为空继续，不为空，返回模板正在导入
        Boolean allCount = stringRedisTemplate.opsForHash().hasKey(importKey, "allCount");
        if (allCount) {
            return new ResultData(Result.SUCCESS, "模板正在导入");
        }

        stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", 0 + "");
        stringRedisTemplate.expire(importKey, 30, TimeUnit.MINUTES);
        stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allSuccessCount", 0 + "");
        stringRedisTemplate.opsForHash().putIfAbsent(importKey, "processCount", "");
        stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "");

        String fpath = fmUploadDir;
        File targetFile = new File(fpath);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        String fileName = "bill_daily.xlsx";
        int dot = mFile.getOriginalFilename().lastIndexOf('.');
        fileName = fileName + mFile.getOriginalFilename().substring(dot, mFile.getOriginalFilename().length());

        File lFile = new File(fpath + File.separator + fileName);

        FileOutputStream fos = null;
        BufferedInputStream fs = null;
        try {
            fos = new FileOutputStream(lFile);
            fs = (BufferedInputStream) mFile.getInputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = fs.read(buffer)) != -1) {
                fos.write(buffer, 0, len);
            }
            fos.close();
            fs.close();
        } catch (Exception e) {
            stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS);
            stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", "1");
            stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "1");
            logger.error(e.getMessage());
            return new ResultData(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败");
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS);
                    stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", "1");
                    stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "1");
                    logger.error(e.getMessage());
                    return new ResultData(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败");
                }
            }
            if (fs != null) {
                try {
                    fs.close();
                } catch (IOException e) {
                    stringRedisTemplate.expire(importKey, 3, TimeUnit.SECONDS);
                    stringRedisTemplate.opsForHash().putIfAbsent(importKey, "allCount", "1");
                    stringRedisTemplate.opsForHash().putIfAbsent(importKey, "failCount", "1");
                    logger.error(e.getMessage());
                    return new ResultData(ErrorCode.MEM_IMPORT_ERR.getCode(), "模板上传失败");
                }
            }
        }

        billDailyAsyncTask.importExcelData(lFile, user, importKey, tenantId);

        return new ResultData(Result.SUCCESS, "模板正在导入");
    }

    @GetMapping("/queryTemplateCount")
    @SystemControllerLog(description = "日常费用账单-导入数据查询")
    public ResultData queryTemplateCount() {
        String importKey = Constant.importMemPrev + "bill_daily_" + getUser().getId();
        Map entries = stringRedisTemplate.opsForHash().entries(importKey);
        logger.info(JSONArray.toJSONString(entries) + ">>>>>>>>>>>>>>>>>>>>>1");
        if (entries.size() < 4) {
            entries.clear();
            return new ResultData(Result.SUCCESS, "ok", entries);
        }
        String allCount = entries.get("allCount").toString();
        String allSuccessCount = entries.get("allSuccessCount").toString();
        String processCount = entries.get("processCount").toString();
        String failCount = entries.get("failCount").toString();

        if (StringUtils.isNotBlank(failCount) && allCount.equals(failCount)) {//stringRedisTemplate.expire(userId,1,TimeUnit.SECONDS);
            logger.info(JSONArray.toJSONString(entries) + ">>>>>>>>>>>>>>>>>>>>>2");
            //完全失败
            stringRedisTemplate.opsForHash().delete(importKey, "allCount");
            stringRedisTemplate.opsForHash().delete(importKey, "allSuccessCount");
            stringRedisTemplate.opsForHash().delete(importKey, "processCount");
            stringRedisTemplate.opsForHash().delete(importKey, "failCount");
            return new ResultData(ErrorCode.MEM_IMPORT_ERR);
        }
        //导入完成
        if (StringUtils.isNotBlank(allSuccessCount) && allSuccessCount.equals(processCount)) {
            ResultData ok = new ResultData(Result.SUCCESS, "ok", entries);
            stringRedisTemplate.opsForHash().delete(importKey, "allCount");
            stringRedisTemplate.opsForHash().delete(importKey, "allSuccessCount");
            stringRedisTemplate.opsForHash().delete(importKey, "processCount");
            stringRedisTemplate.opsForHash().delete(importKey, "failCount");
            return ok;
        }
        return new ResultData(Result.SUCCESS, "查询成功", entries);
    }

    @GetMapping("exportBill")
    @SystemControllerLog(description = "日常费用账单-导出")
    public void exportBill(@ModelAttribute WxBillDaily wxBillDaily, HttpServletRequest request, HttpServletResponse response) {
        wxBillDaily.setTenantId(getTenantId());
        wxBillDailyService.exportBill(request, response, wxBillDaily);
    }

}
