package com.crm.custom.controller;

import com.crm.custom.service.CustomFileService;
import com.crm.custom.service.PushMessageFeignService;
import com.crm.custom.service.SysConfigService;
import com.crm.login.rely.backend.controller.BaseLoginController;
import com.crm.rely.backend.core.constant.*;
import com.crm.rely.backend.core.dto.base.BaseResultDto;
import com.crm.rely.backend.core.dto.custom.file.CustomFileDto;
import com.crm.rely.backend.core.entity.websocket.WebsocketPushMessageEntity;
import com.crm.rely.backend.core.entity.websocket.bank.file.WebSocketCustomFileEntity;
import com.crm.rely.backend.core.pojo.table.SysConfigTable;
import com.crm.rely.backend.core.exception.ServiceException;
import com.crm.rely.backend.model.entity.custom.file.CustomFileAddAndUpdateEntity;
import com.crm.rely.backend.model.entity.custom.file.CustomFileAllEntity;
import com.crm.rely.backend.model.entity.custom.file.CustomFileApproveEntity;
import com.crm.rely.backend.model.entity.custom.file.CustomFileDeleteEntity;
import com.crm.rely.backend.model.entity.custom.info.CustomInfoEntity;
import com.crm.rely.backend.model.entity.custom.info.InfoEntity;
import com.crm.rely.backend.model.entity.user.info.UserInfoEntity;
import com.crm.rely.backend.util.GetIpAndMac;
import com.crm.rely.backend.util.QRCodeImgeUtil;
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.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author: houn
 */
@RestController
@RequestMapping("/custom/file")
public class CustomFileController extends BaseLoginController {

    @Autowired
    private CustomFileService customFileService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private PushMessageFeignService pushMessageFeignService;

    @PostMapping("/upload/{type}")
    public BaseResultDto upload(@RequestParam(value = "file", required = false) MultipartFile file, @PathVariable("type") Integer type, HttpServletRequest req,
                                CustomInfoEntity infoEntity) throws Exception {


        return upload(file, type, null, req, infoEntity);
    }

    @PostMapping("/upload/{type}/{id}")
    public BaseResultDto upload(@RequestParam(value = "file", required = false) MultipartFile file, @PathVariable("type") Integer type, @PathVariable("id") Long id,
                                HttpServletRequest req, CustomInfoEntity infoEntity) throws Exception {

        customFileService.validated(file);

        CustomFileAddAndUpdateEntity customFileAddAndUpdateEntity = new CustomFileAddAndUpdateEntity();
        customFileAddAndUpdateEntity.setCustomId(infoEntity.getId());
        customFileAddAndUpdateEntity.setType(type);
        customFileAddAndUpdateEntity.setId(id);
        customFileAddAndUpdateEntity.setIp(GetIpAndMac.getIp(req));
        customFileAddAndUpdateEntity.setTime(new Date());
        customFileAddAndUpdateEntity.setUser(infoEntity.getId());
        customFileAddAndUpdateEntity.setUploadUserType(1);
        CustomFileDto customFileDto = customFileService.save(customFileAddAndUpdateEntity, file);

        setCache(type, customFileDto, infoEntity);
        return BaseResultDto.success(Constants.UPLOAD_SUCCESS, customFileDto);
    }

    @PostMapping("/delete")
    public BaseResultDto delete(@RequestBody @Validated CustomFileDeleteEntity entity, CustomInfoEntity infoEntity) throws Exception {

        entity.setCustomId(infoEntity.getId());
        customFileService.delete(entity);

        return BaseResultDto.success();
    }

    @PostMapping("/manager/delete")
    @FeignClientAnnotation
    public BaseResultDto managerDelete(@RequestBody @Validated CustomFileDeleteEntity entity) throws Exception {

        customFileService.delete(entity);

        return BaseResultDto.success();
    }

    @PostMapping("/manager/upload/{customId}/{type}")
    @FeignClientAnnotation
    public BaseResultDto mangerUpload(@RequestParam(value = "file", required = false) MultipartFile file, @PathVariable("customId") Long customId, @PathVariable("type") Integer type, HttpServletRequest req,
                                      UserInfoEntity infoEntity) throws Exception {

        customFileService.validated(file);

        CustomFileAddAndUpdateEntity customFileAddAndUpdateEntity = new CustomFileAddAndUpdateEntity();
        customFileAddAndUpdateEntity.setCustomId(customId);
        customFileAddAndUpdateEntity.setType(type);
        customFileAddAndUpdateEntity.setIp(GetIpAndMac.getIp(req));
        customFileAddAndUpdateEntity.setTime(new Date());
        customFileAddAndUpdateEntity.setUser(infoEntity.getId());
        customFileAddAndUpdateEntity.setUploadUserType(2);

        CustomFileDto customFileDto = customFileService.save(customFileAddAndUpdateEntity, file);

        CustomInfoEntity customInfoEntity =
                redisService.getEntity(PrefixEnum.PREFIX_CUSTOM.getCode() +customId, CustomInfoEntity.class);
        if (customInfoEntity != null) {
            setCache(type, customFileDto, customInfoEntity);
        }


        return BaseResultDto.success(Constants.UPLOAD_SUCCESS, customFileDto);
    }

    @PostMapping("/manager/upload/{customId}/{type}/{id}")
    @FeignClientAnnotation
    public BaseResultDto mangerUpload(@RequestParam(value = "file", required = false) MultipartFile file, @PathVariable("customId") Long customId, @PathVariable("type") Integer type, @PathVariable("id") Long id,
                                      HttpServletRequest req, UserInfoEntity infoEntity) throws Exception {

        customFileService.validated(file);

        CustomFileAddAndUpdateEntity customFileAddAndUpdateEntity = new CustomFileAddAndUpdateEntity();
        customFileAddAndUpdateEntity.setCustomId(customId);
        customFileAddAndUpdateEntity.setType(type);
        customFileAddAndUpdateEntity.setId(id);
        customFileAddAndUpdateEntity.setIp(GetIpAndMac.getIp(req));
        customFileAddAndUpdateEntity.setTime(new Date());
        customFileAddAndUpdateEntity.setUser(infoEntity.getId());
        customFileAddAndUpdateEntity.setUploadUserType(2);

        CustomFileDto customFileDto = customFileService.save(customFileAddAndUpdateEntity, file);

        return BaseResultDto.success(Constants.UPLOAD_SUCCESS, customFileDto);
    }

    @PostMapping("/list")
    public BaseResultDto list(CustomInfoEntity infoEntity) throws Exception {

        CustomFileAllEntity entity = new CustomFileAllEntity();
        entity.setCustomId(infoEntity.getId());
        List<CustomFileDto> customFileDtos = customFileService.getAllFiles(entity);

        if (customFileDtos == null) {
            customFileDtos = new ArrayList<>(0);
        }
        return BaseResultDto.success(Constants.SUCCESS, customFileDtos);
    }

    @PostMapping("/manager/search/list")
    @FeignClientAnnotation
    public BaseResultDto manageSearchList(@RequestBody @Validated CustomFileAllEntity entity) throws Exception {

        List<CustomFileDto> customFileDtos = customFileService.getAllFiles(entity);

        if (customFileDtos == null) {
            customFileDtos = new ArrayList<>(0);
        }
        return BaseResultDto.success(Constants.SUCCESS, customFileDtos);
    }

    @PostMapping("/manager/approve")
    @FeignClientAnnotation
    public BaseResultDto manageApprove(@RequestBody @Validated CustomFileApproveEntity entity) throws Exception {

        customFileService.approve(entity);

        return BaseResultDto.success(Constants.APPROVE_SUCCESS);
    }

    @GetMapping("/mobile")
    public void websocketMobile(HttpServletRequest req, HttpServletResponse response) throws Exception {
        String token = req.getHeader(Constants.ACCESS_TOKEN);
        String localhost;
        try {
            SysConfigTable sysConfigTable = sysConfigService.getByCode(GlobalConfigConstants.WEB_MY_URE_CONFIG);
            localhost = sysConfigTable.getValue();
        } catch (ServiceException e) {
            localhost = GetIpAndMac.getIpAndPort();
        }
        String mobileUploadIndex;
        try {
            SysConfigTable sysConfigTable = sysConfigService.getByCode(GlobalConfigConstants.WEB_MY_URL_MOBILE_UPLOAD_CONFIG);
            mobileUploadIndex = sysConfigTable.getValue();
        } catch (ServiceException e) {
            mobileUploadIndex = null;
        }

        BufferedImage bufferedImage = QRCodeImgeUtil.getQRCodeImge(localhost + mobileUploadIndex + "?" + Constants.ACCESS_TOKEN + "=" + token);

        response.setContentType("image/jpg");
        try {
            OutputStream out = response.getOutputStream();

            ImageIO.write(bufferedImage, "jpg", out);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void pushMessage(HttpServletRequest req, CustomFileDto customFileDto) {
        WebSocketCustomFileEntity webSocketCustomFileEntity = new WebSocketCustomFileEntity();
        BeanUtils.copyProperties(customFileDto, webSocketCustomFileEntity);
        webSocketCustomFileEntity.setNewsType(NewsConstants.NEWS_CUSTOM_FILE);
        String accessToken = req.getHeader(Constants.ACCESS_TOKEN);
        WebsocketPushMessageEntity websocketPushMessageEntity = new WebsocketPushMessageEntity();
        websocketPushMessageEntity.setToken(accessToken);
        websocketPushMessageEntity.setData(webSocketCustomFileEntity);
        try {
            pushMessageFeignService.pushMessageToTokenNotice(websocketPushMessageEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void setCache(int type, CustomFileDto customFileDto, CustomInfoEntity infoEntity) throws Exception {
        boolean push = false;
        if (infoEntity.getFiles() != null && infoEntity.getFiles().size() > 0) {

            for (CustomFileDto infoEntityFile : infoEntity.getFiles()) {
                if (infoEntityFile.getType().equals(type)) {
                    BeanUtils.copyProperties(customFileDto, infoEntityFile);
                    push = true;
                    break;
                }
            }
        }

        if (!push) {
            List<CustomFileDto> fileDtos = new ArrayList<>(1);
            infoEntity.setFiles(fileDtos);
        }
        saveLoginInfo(infoEntity);
    }

}
