package com.yonge.cooleshow.tenant.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.microsvc.toolkit.common.response.paging.PageInfo;
import com.microsvc.toolkit.common.response.paging.QueryInfo;
import com.microsvc.toolkit.common.response.template.R;
import com.microsvc.toolkit.common.tools.DownloadManager;
import com.microsvc.toolkit.common.webportal.exception.BizException;
import com.microsvc.toolkit.middleware.oss.OssPluginContext;
import com.microsvc.toolkit.middleware.oss.impl.TencentOssPlugin;
import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.biz.dal.entity.TenantActivationCode;
import com.yonge.cooleshow.biz.dal.entity.TenantAlbum;
import com.yonge.cooleshow.biz.dal.entity.TenantAlbumPurchase;
import com.yonge.cooleshow.biz.dal.entity.TenantInfo;
import com.yonge.cooleshow.biz.dal.entity.TenantStaff;
import com.yonge.cooleshow.biz.dal.entity.UserOrder;
import com.yonge.cooleshow.biz.dal.service.OssFileService;
import com.yonge.cooleshow.biz.dal.service.TenantActivationCodeService;
import com.yonge.cooleshow.biz.dal.service.TenantAlbumPurchaseService;
import com.yonge.cooleshow.biz.dal.service.TenantAlbumService;
import com.yonge.cooleshow.biz.dal.service.TenantInfoService;
import com.yonge.cooleshow.biz.dal.service.TenantStaffService;
import com.yonge.cooleshow.biz.dal.service.UserOrderService;
import com.yonge.cooleshow.biz.dal.wrapper.OssFileWrapper;
import com.yonge.cooleshow.biz.dal.wrapper.TenantActivationCodeWrapper;
import com.yonge.cooleshow.common.controller.BaseController;
import com.yonge.cooleshow.common.entity.HttpResponseResult;
import com.yonge.cooleshow.common.enums.EActivationCode;
import com.yonge.cooleshow.tenant.vo.TenantActivationCodeVo;
import com.yonge.toolset.utils.easyexcel.ExcelDataReader;
import com.yonge.toolset.utils.easyexcel.ExcelUtils;
import com.yonge.toolset.utils.http.HttpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.text.MessageFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;


@Slf4j
@Validated
@RestController
@RequestMapping("${app-config.url.tenant:}/tenantActivationCode")
@Api(tags = "机构激活码")
public class TenantActivationCodeController extends BaseController {

    @Autowired
    private TenantActivationCodeService tenantActivationCodeService;

    @Autowired
    private TenantAlbumPurchaseService tenantAlbumPurchaseService;

    @Resource
    private SysUserFeignService sysUserFeignService;

    @Autowired
    private TenantInfoService tenantInfoService;

    @Autowired
    private TenantStaffService tenantStaffService;
    @Autowired
    private OssPluginContext ossPluginContext;
    @Autowired
    private UserOrderService userOrderService;
    @Autowired
    private TenantAlbumService tenantAlbumService;
    @Autowired
    private OssFileService ossFileService;

    @ApiOperation(value = "详情", notes = "机构激活码-根据详情ID查询单条, 传入id")
//    @GetMapping("/detail/{id}")
    public R<TenantActivationCodeVo.TenantActivationCode> detail(@PathVariable("id") Long id) {

        TenantActivationCode wrapper = tenantActivationCodeService.detail(id);

        return R.from(TenantActivationCodeVo.TenantActivationCode.from(JSON.toJSONString(wrapper)));
    }

    @ApiOperation(value = "查询分页", notes = "机构激活码- 传入 TenantActivationCodeVo.TenantActivationCodeQuery")
    @PostMapping("/page")
    public HttpResponseResult<PageInfo<TenantActivationCodeWrapper.TenantActivationCode>> page(
            @RequestBody TenantActivationCodeWrapper.TenantActivationCodeQuery query) {
        TenantInfo tenantInfo = getTenantInfo();
        query.setTenantId(tenantInfo.getId());
        // 查询数据
        String activationTime = query.getActivationTime();
        if (StringUtils.isNotEmpty(activationTime)) {
            Date parse = new SimpleDateFormat("yyyy-MM").parse(activationTime, new ParsePosition(0));
            query.setActivationStartTime(parse);
            Calendar instance = Calendar.getInstance();
            instance.setTime(parse);
            instance.add(Calendar.MONTH, 1);
            instance.add(Calendar.DATE, -1);
            instance.set(Calendar.HOUR_OF_DAY, 23);
            instance.set(Calendar.MINUTE, 59);
            instance.set(Calendar.MILLISECOND, 59);
            query.setActivationEndTime(instance.getTime());
        }
        IPage<TenantActivationCodeWrapper.TenantActivationCode> pages =
                tenantActivationCodeService.selectPage(QueryInfo.getPage(query), query);
        PageInfo<TenantActivationCodeWrapper.TenantActivationCode> pageInfo = QueryInfo.pageInfo(pages,
                pages.getRecords());

        if (query.getTenantAlbumPurchaseId() != null) {
            TenantActivationCodeWrapper.TenantActivationCode extra =
                    new TenantActivationCodeWrapper.TenantActivationCode();
            TenantAlbumPurchase purchase = tenantAlbumPurchaseService.getById(query.getTenantAlbumPurchaseId());
            extra.setActiveQuantity(purchase.getActiveQuantity());
            pageInfo.setExtra(extra);
        }

        return succeed(pageInfo);
    }

    @ApiOperation(value = "激活码发放", notes = "机构激活码- 传入 TenantActivationCodeVo.TenantActivationCodeSend")
    @PostMapping("/send")
    public HttpResponseResult<Boolean> send(@Validated @RequestBody TenantActivationCodeVo.TenantActivationCodeSend send) {
        TenantInfo tenantInfo = getTenantInfo();
        tenantActivationCodeService.sendActivationCode(tenantInfo.getId(), send.getTenantAlbumPurchaseId(),
                send.getActivationCodeList(),
                send.getStudentIdList());
        return succeed();
    }


    @ApiOperation(value = "激活码重发", notes = "机构激活码- 传入 TenantActivationCodeVo.TenantActivationCodeSend")
    @PostMapping("/resend")
    public HttpResponseResult<Boolean> resend(@Validated @RequestBody TenantActivationCodeVo.TenantActivationCodeResend send) {
        TenantInfo tenantInfo = getTenantInfo();
        tenantActivationCodeService.resend(send.getCode(),send.getUserId(),tenantInfo.getId(),send.getTenantAlbumPurchaseId());
        return succeed();
    }

    @ApiOperation(value = "激活码批量重发", notes = "机构激活码- 传入 TenantActivationCodeVo.TenantActivationCodeSend")
    @PostMapping("/batchResend")
    public HttpResponseResult<Boolean> batchResend(@Validated @RequestBody TenantActivationCodeVo.TenantActivationCodeSend send) {
        TenantInfo tenantInfo = getTenantInfo();
        tenantActivationCodeService.batchResend(tenantInfo, send.getTenantAlbumPurchaseId(),
                send.getActivationCodeList(), send.getStudentIdList());
        return succeed();
    }

    @ApiOperation(value = "激活码发放取消", notes = "传入 激活码的ID")
    @PostMapping("/sendCancel")
    public HttpResponseResult<Boolean> sendCancel(@RequestParam("id") Long id) {
        TenantInfo tenantInfo = getTenantInfo();
        TenantActivationCode activationCode = tenantActivationCodeService.getById(id);
        tenantActivationCodeService.sendCancel(tenantInfo, activationCode);
        return succeed();
    }

    @ApiOperation(value = "批量激活码发放取消", notes = "传入 激活码的ID")
    @PostMapping("/batchSendCancel")
    public HttpResponseResult<Boolean> batchSendCancel(@RequestParam("ids") String ids) {
        tenantActivationCodeService.batchSendCancel(getTenantInfo(), ids);
        return succeed();
    }

    @GetMapping("/exportActiveCode")
    @ApiOperation(value = "导出模板")
    public HttpResponseResult<OssFileWrapper.ExportFile> exportActiveCode(HttpServletResponse response, String orderNo) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("请登录");
        }
        Long tenantId = sysUser.getTenantId();

        TenantActivationCodeWrapper.TenantActivationCodeQuery query =
                new TenantActivationCodeWrapper.TenantActivationCodeQuery();
        query.setTenantId(tenantId);
        query.setActivationStatus(false);
        query.setTenantAlbumPurchaseId(Long.valueOf(orderNo));
        query.setSendStatus(EActivationCode.WAIT);
        query.setActivationStatus(false);
        query.setPage(1);
        query.setRows(9999);
        IPage<TenantActivationCodeWrapper.TenantActivationCode> queryInfo =
                tenantActivationCodeService.selectPage(QueryInfo.getPage(query), query);
        List<TenantActivationCodeWrapper.TenantActivationCode> rows = queryInfo.getRecords();
        if (rows.isEmpty()) {
            throw new BizException("没有可导出数据");
        }

        List<TenantActivationCodeWrapper.ExportTemplate> templates = JSONArray.parseArray(JSON.toJSONString(rows), TenantActivationCodeWrapper.ExportTemplate.class);
        templates.forEach(next->next.setActivationPhone(""));

        TenantAlbumPurchase tenantAlbumPurchase = tenantAlbumPurchaseService.getById(Long.valueOf(orderNo));
        TenantAlbum tenantAlbum = tenantAlbumService.getById(tenantAlbumPurchase.getTenantAlbumId());
        UserOrder userOrder = userOrderService.getByOrderNo(tenantAlbumPurchase.getOrderNo());

        String format = new SimpleDateFormat("yyyyMMddHHmm").format(userOrder.getCreateTime());


        OssFileWrapper.ExportFile exportFile = ossFileService.uploadFile(templates,
                TenantActivationCodeWrapper.ExportTemplate.class, format + tenantAlbum.getName(), "激活码");
        return succeed(exportFile);
    }


    private TenantActivationCodeWrapper.ExportFile generateExportExcelFile(List<?> orderExports, Class<?> clazz, String fileName, String sheetName) {

        // OSS上传文件目录
        String uploadOssPath = MessageFormat.format("excel-download/{0}", DateTime.now().toString("yyyy-MM"));

        // 文件上传下载地址
        String uploadPath = MessageFormat.format("{0}/{1}-{2}.xlsx", uploadOssPath, String.valueOf(IdWorker.getId()), DateTime.now().toString("MMddHHmmss"));

        // 本地文件地址
        String localPath = DownloadManager.getInstance().path(uploadPath);
        log.debug("pageExport localPath={}", localPath);

        // 模板文件保存在springboot项目的resources/static下
        // Resource resource = new ClassPathResource("static/预报名模板导出.xlsx");

        EasyExcel
                .write(localPath, clazz)
                //.withTemplate(resource.getStream()) // 利用模板的输出流
                .sheet(0, sheetName)
                .doWrite(orderExports);

        // 上传本地文件到OSS服务器
        String downloadPath = ossPluginContext.getPluginService(TencentOssPlugin.PLUGIN_NAME)
                .uploadFile(uploadOssPath, new File(localPath));
        log.debug("pageExport downloadPath={}", downloadPath);

        // 删除本地缓存文件
        DownloadManager.getInstance().deleteOnExit(localPath);

        // 学生统计下载
        return TenantActivationCodeWrapper.ExportFile
                .builder()
                .fileName(MessageFormat.format("{0}.xlsx", fileName))
                .downloadPath(HttpUtil.getSortUrl(downloadPath))
                .build();
    }



    @GetMapping("/exportOrderCode")
    @ApiOperation(value = "导出订单激活码模板")
    public HttpResponseResult<TenantActivationCodeWrapper.ExportFile> exportOrderCode(HttpServletResponse response, String orderNo) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("请登录");
        }
        Long tenantId = sysUser.getTenantId();

        TenantActivationCodeWrapper.TenantActivationCodeQuery query =
                new TenantActivationCodeWrapper.TenantActivationCodeQuery();
        query.setTenantId(tenantId);
        query.setActivationStatus(false);
        query.setOrderNo(orderNo);
        query.setPage(1);
        query.setRows(9999);
        IPage<TenantActivationCodeWrapper.TenantActivationCode> queryInfo =
                tenantActivationCodeService.selectPage(QueryInfo.getPage(query), query);
        List<TenantActivationCodeWrapper.TenantActivationCode> rows = queryInfo.getRecords();
        if (rows.isEmpty()) {
            throw new BizException("没有可导出数据");
        }

        List<TenantActivationCodeWrapper.ExportTemplate> templates = JSONArray.parseArray(JSON.toJSONString(rows), TenantActivationCodeWrapper.ExportTemplate.class);


        TenantActivationCodeWrapper.ExportFile exportFile = generateExportExcelFile(templates, TenantActivationCodeWrapper.ExportTemplate.class, "激活码导出", "激活码");
        return succeed(exportFile);
    }

    @PostMapping("/importActiveCode")
    @ApiOperation(value = "导入", notes = "传入file")
    public HttpResponseResult<Object> importActiveCode(
            @RequestParam("file") MultipartFile file,
            @RequestParam("tenantAlbumPurchaseId") Long tenantAlbumPurchaseId) {
        if (null == file) {
            return HttpResponseResult.failed("请上传文件");
        }
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null || null == user.getId()) {
            return failed(HttpStatus.FORBIDDEN, "请登录");
        }
        TenantStaff tenantStaff = tenantStaffService.getByUserId(user.getId());
        if (tenantStaff == null) {
            return HttpResponseResult.failed("权限不足");
        }

        try {
            ExcelDataReader<TenantActivationCodeWrapper.ImportTemplate> reader =
                    ExcelUtils.getReader(TenantActivationCodeWrapper.ImportTemplate.class, file);
            return tenantActivationCodeService.importActiveCode(reader.getDataList(), user.getTenantId(), user.getId(),
                    tenantAlbumPurchaseId);
        } catch (Exception e) {
            log.error("导入激活码失败:"+JSON.toJSONString(e.getMessage()));
            return HttpResponseResult.failed("文件解析错误");
        }
    }

    @ApiOperation(value = "新增", notes = "机构激活码- 传入 TenantActivationCodeVo.TenantActivationCode")
//    @PostMapping("/save")
    public R<JSONObject> add(@Validated @RequestBody TenantActivationCodeVo.TenantActivationCode tenantActivationCodeVo) {

        // 新增数据
        tenantActivationCodeService.save(JSON.parseObject(tenantActivationCodeVo.jsonString(),
                TenantActivationCode.class));

        return R.defaultR();
    }

    @ApiOperation(value = "修改", notes = "机构激活码- 传入 TenantActivationCodeVo.TenantActivationCode")
//    @PostMapping("/update")
    public R<JSONObject> update(@Validated @RequestBody TenantActivationCodeVo.TenantActivationCode tenantActivationCodeVo) {

        // 更新数据
        tenantActivationCodeService.updateById(JSON.parseObject(tenantActivationCodeVo.jsonString(),
                TenantActivationCode.class));

        return R.defaultR();
    }

    @ApiOperation(value = "删除", notes = "机构激活码- 传入id")
//    @PostMapping("/remove")
    public R<Boolean> remove(@RequestParam Long id) {

        return R.from(tenantActivationCodeService.removeById(id));
    }

    private TenantInfo getTenantInfo() {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        TenantInfo tenantInfo = tenantInfoService.getById(sysUser.getTenantId());
        if (tenantInfo == null) {
            throw new BizException("非法请求");
        }
        return tenantInfo;
    }
}