package com.ruoyi.web.work.service.impl;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.work.api.util.AppUtil;
import com.ruoyi.web.work.domain.*;
import com.ruoyi.web.work.domain.dto.JTaskCompleteDto;
import com.ruoyi.web.work.domain.dto.ResumeDeliverDto;
import com.ruoyi.web.work.domain.dto.ResumeInviteDto;
import com.ruoyi.web.work.domain.dto.YTaskCompleteDto;
import com.ruoyi.web.work.domain.vo.ReceiveListVo;
import com.ruoyi.web.work.domain.vo.ReceiveVo;
import com.ruoyi.web.work.mapper.ResumeDeliverMapper;
import com.ruoyi.web.work.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author lsw
 * @date 2024-06-13
 */
@Service
public class ResumeDeliverServiceImpl extends ServiceImpl<ResumeDeliverMapper, ResumeDeliver> implements IResumeDeliverService {
    @Autowired
    private ResumeDeliverMapper resumeDeliverMapper;

    @Autowired
    private IPositionService positionService;

    @Autowired
    private IResumeService resumeService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IEnterpriseService enterpriseService;

    @Autowired
    private IPayService payService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private Environment env;

    @Override
    public List<ResumeDeliver> selectList(ResumeDeliver resumeDeliver) {
        return resumeDeliverMapper.selectList(resumeDeliver);
    }

    @Override
    public AjaxResult send(Long id) {
        if (AppUtil.getUser().getIsAuthentication() != 1) {
            return AjaxResult.error(7878, "您需要实名认证才能投递简历");
        }
        Resume resume = resumeService.getById(AppUtil.getUser().getId());
        if (StringUtils.isEmpty(resume.getName())) {
            return AjaxResult.error(7979, "请先完善简历再投递");
        }
        Position position = positionService.getById(id);
        if (position == null || position.getState() != 0 || position.getAudit() != 1) {
            return AjaxResult.error("该职位不存在或已下架");
        }
        if (position.getUserId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("不能自己报名自己");
        }
        ResumeDeliver resumeDeliver = resumeDeliverMapper.check(position.getId(), AppUtil.getUser().getId());
        if (resumeDeliver != null) {
            return AjaxResult.error("请勿重复投递简历");
        }
        resumeDeliver = new ResumeDeliver();
        resumeDeliver.setUserId(AppUtil.getUser().getId());
        resumeDeliver.setType(position.getType());
        resumeDeliver.setPositionId(position.getId());
        resumeDeliver.setEnterpriseId(position.getUserId());
        if (!save(resumeDeliver)) {
            throw new ServiceException("投递简历失败");
        }
        return AjaxResult.success();
    }

    @Transactional
    @Override
    public AjaxResult agree(ResumeDeliverDto dto) throws ParseException {
        ResumeDeliver resumeDeliver = getById(dto.getId());
        if (resumeDeliver == null || !resumeDeliver.getUserId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("面试不存在或非法操作");
        }
        //兼职接单成功，把兼职设置成进行中...
        if (resumeDeliver.getType() == 1 && resumeDeliver.getIsAccept() == 0 && dto.getIsAccept() == 1) {
            System.out.println("zzzzz");
            String key = CacheConstants.APP_DELIVER + resumeDeliver.getId() + "-" + AppUtil.getUser().getId();
            if (redisCache.getCacheObject(key) == null) {
                resumeDeliver.setIsExpire(1);
                updateById(resumeDeliver);
                return AjaxResult.error("抱歉你的兼职邀请已经超时无效了");
            }
            redisCache.deleteObject(key);
            Position position = new Position();
            position.setId(resumeDeliver.getPositionId());
            position.setComplete(1);
            if (!positionService.updateById(position)) {
                throw new ServiceException("更新兼职信息失败");
            }
        }
        resumeDeliver.setIsAccept(dto.getIsAccept());
        if (!updateById(resumeDeliver)) {
            throw new ServiceException("接受或拒绝面试邀请失败");
        }
        if (resumeDeliver.getType() == 1) {
            sendMessage(resumeDeliver);
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult invite(ResumeInviteDto dto) throws ParseException {
        ResumeDeliver resumeDeliver = getById(dto.getId());
        if (resumeDeliver == null || !resumeDeliver.getEnterpriseId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("简历不存在或非法操作");
        }
        if (resumeDeliver.getIsAccept() == 2) {
            return AjaxResult.error("求职者已拒绝，无法重复发送");
        }
        if (resumeDeliver.getIsAccept() == 1) {
            return AjaxResult.error("求职者已同意，请及时安排线下面试");
        }
        if (resumeDeliver.getState() == 1) {
            return AjaxResult.error("已发送邀请，等待求职者同意");
        }
        resumeDeliver.setState(1);
        resumeDeliver.setInviteTime(dto.getInviteTime());
        if (!updateById(resumeDeliver)) {
            throw new ServiceException("发送面试邀请失败");
        }
        sendMessage(resumeDeliver);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult agreeApplication(Long id) throws ParseException {
        ResumeDeliver resumeDeliver = getById(id);
        if (resumeDeliver == null || !resumeDeliver.getEnterpriseId().equals(AppUtil.getUser().getId()) || resumeDeliver.getType() == 0) {
            return AjaxResult.error("简历不存在或非法操作");
        }
        if (resumeDeliver.getIsExpire() == 1) {
            return AjaxResult.error("对方超时未操作(已过期)");
        }
        List<ResumeDeliver> list = selectList(new ResumeDeliver().setPositionId(resumeDeliver.getPositionId()).setState(1).setIsExpire(0));
        if (!list.isEmpty() && list.size() > 0) {
            return AjaxResult.error("排队中...你已发出一份兼职邀请，请等待对方答复后或者1小时无回应再操作");
        }
        if (resumeDeliver.getIsAccept() == 2) {
            return AjaxResult.error("兼职者已拒绝，无法重复发送");
        }
        if (resumeDeliver.getIsAccept() == 1) {
            return AjaxResult.error("兼职者已同意，请留意工作进度");
        }
        if (resumeDeliver.getState() == 1) {
            return AjaxResult.error("已发送邀请，等待兼职者同意");
        }
        resumeDeliver.setState(1);
        resumeDeliver.setAuditTime(new Date());
        if (!updateById(resumeDeliver)) {
            throw new ServiceException("发送兼职邀请失败");
        }
        //用户的接单信息缓存起来60分钟，超时无效。
        String key = CacheConstants.APP_DELIVER + resumeDeliver.getId() + "-" + resumeDeliver.getUserId();
        redisCache.setCacheObject(key, resumeDeliver, 60, TimeUnit.MINUTES);
        sendMessage(resumeDeliver);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult complete(Long id) {
        ResumeDeliver resumeDeliver = getById(id);
        if (resumeDeliver == null || !resumeDeliver.getEnterpriseId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("简历不存在或非法操作");
        }
        resumeDeliver.setIsAccept(3);
        if (!updateById(resumeDeliver)) {
            throw new ServiceException("操作面试失败");
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult detail(Long id) {
        ResumeDeliver resumeDeliver = getById(id);
        if (resumeDeliver == null || !resumeDeliver.getEnterpriseId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("简历不存在或非法操作");
        }
        if (resumeDeliver.getIsRead() == 0) {
            resumeDeliver.setIsRead(1);
            updateById(resumeDeliver);
        }
        Resume resume = resumeService.getById(resumeDeliver.getUserId());
        return AjaxResult.success(resume);
    }

    @Override
    public AjaxResult remove(Long id) {
        ResumeDeliver resumeDeliver = getById(id);
        if (resumeDeliver == null || !resumeDeliver.getUserId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("简历不存在或非法操作");
        }
        if (resumeDeliver.getType() == 1 && resumeDeliver.getIsAccept() == 1) {
            return AjaxResult.error("你已同意兼职，无法删除该报名");
        }
        if (!removeById(id)) {
            throw new ServiceException("删除投递失败");
        }
        return AjaxResult.success();
    }

    @Override
    public List<ReceiveVo> receive(ResumeDeliver resumeDeliver) {
        return resumeDeliverMapper.receive(resumeDeliver);
    }

    @Override
    public List<ReceiveListVo> receiveList(ResumeDeliver resumeDeliver) {
        return resumeDeliverMapper.receiveList(resumeDeliver);
    }

    @Override
    public void sendMessage(ResumeDeliver resumeDeliver) throws ParseException {
        JSONObject jsonObject = JSONUtil.parseObj(HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + env.getProperty("wx.appid") + "&secret=" + env.getProperty("wx.appSecret")));
        JSONObject body = new JSONObject();
        body.set("appid", env.getProperty("wx.appid"));
        JSONObject content = new JSONObject();
        //面试邀请通知
        if (resumeDeliver.getState() == 1 && resumeDeliver.getIsAccept() == 0 && resumeDeliver.getType() == 0) {
            Position position = positionService.getById(resumeDeliver.getPositionId());
            Enterprise enterprise = enterpriseService.getById(position.getUserId());
            User user = userService.getById(resumeDeliver.getUserId());
            body.set("touser", user.getOpenId());
            body.set("template_id", "ll-qdaEgbDN4rEod0nJpsjUuSqHT9e12EniZfRPiNqM");
            body.set("page", "pages/user/resume/deliver/invite");
            content.set("thing5", new JSONObject().set("value", enterprise.getName()));//公司名称
            content.set("thing1", new JSONObject().set("value", position.getTitle()));//职位
            content.set("time3", new JSONObject().set("value", DateUtils.formatDate(resumeDeliver.getInviteTime())));//面试时间
            content.set("thing4", new JSONObject().set("value", StringUtils.truncateString(position.getAddress(), 15))); //面试地点
        }
        //接单成功提醒
        if (resumeDeliver.getState() == 1 && resumeDeliver.getIsAccept() == 1 && resumeDeliver.getType() == 1) {
            Position position = positionService.getById(resumeDeliver.getPositionId());
            User user = userService.getById(resumeDeliver.getUserId());
            body.set("touser", user.getOpenId());
            body.set("template_id", "bxOGj5FbyGHSevmWf9yzwpSZDjlFZPnGBeqGgIj9w_o");
            body.set("page", "pages/user/resume/application/task_to_do?role=0");
            content.set("thing4", new JSONObject().set("value", position.getTitle()));//兼职名称
            content.set("thing6", new JSONObject().set("value", "对方已同意接单,请留意工作进度"));//备注
        }
        //接单失败提醒
        if (resumeDeliver.getState() == 1 && resumeDeliver.getIsAccept() == 2 && resumeDeliver.getType() == 1) {
            Position position = positionService.getById(resumeDeliver.getPositionId());
            User user = userService.getById(resumeDeliver.getEnterpriseId());
            body.set("touser", user.getOpenId());
            body.set("template_id", "pyUsW2HqOcXmFETHFUDjuH-ekf05QVc29k0tRaY9wP8");
            body.set("page", "pages/user/resume/application/receive/index");
            content.set("thing3", new JSONObject().set("value", position.getTitle()));//兼职名称
            content.set("thing5", new JSONObject().set("value", "对方拒绝接单，请重新选择接单人员"));//备注
        }
        //兼职报名审核结果通知
        if (resumeDeliver.getState() == 1 && resumeDeliver.getIsAccept() == 0 && resumeDeliver.getType() == 1) {
            Position position = positionService.getById(resumeDeliver.getPositionId());
            User user = userService.getById(resumeDeliver.getUserId());
            body.set("touser", user.getOpenId());
            body.set("template_id", "yhFtY-hzXerPnIxXcYcRCAjQUf8CdLoYEQQi5nBgim0");
            body.set("page", "pages/user/resume/application/invite?type=1");
            content.set("thing1", new JSONObject().set("value", position.getTitle()));//兼职名称
            content.set("amount4", new JSONObject().set("value", position.getSalary() + "元"));//工作报酬
            content.set("phrase5", new JSONObject().set("value", "通过"));//状态
        }
        //兼职薪资到账通知
        if (resumeDeliver.getState() == 1 && resumeDeliver.getIsAccept() == 1 && resumeDeliver.getType() == 1 && resumeDeliver.getIsComplete() == 2) {
            Position position = positionService.getById(resumeDeliver.getPositionId());
            User user = userService.getById(resumeDeliver.getUserId());
            body.set("touser", user.getOpenId());
            body.set("template_id", "87jYTnpeZJnvdQ6gHcscZ96eQYlSXpfGeFU3g9deTeA");
            body.set("page", "pages/user/money/index");
            content.set("thing1", new JSONObject().set("value", position.getTitle()));//兼职名称
            content.set("amount4", new JSONObject().set("value", position.getSalary()));//佣金金额
            content.set("thing5", new JSONObject().set("value", "平台充值到账号余额"));//到账渠道
        }
        body.set("data", content);
        String result = HttpUtil.post("https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + jsonObject.getStr("access_token"), body.toString());
        System.out.println("body：" + body);
        System.out.println("小程序订阅消息：" + result);
    }

    @Override
    public AjaxResult yTaskComplete(YTaskCompleteDto dto) {
        ResumeDeliver resumeDeliver = getById(dto.getId());
        if (resumeDeliver == null || !resumeDeliver.getUserId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("兼职任务不存在或非法操作");
        }
        if (resumeDeliver.getIsComplete() == 2) {
            return AjaxResult.error("任务已完成");
        }
        resumeDeliver.setIsComplete(1);
        resumeDeliver.setCompleteMsg(dto.getCompleteMsg());
        if (!updateById(resumeDeliver)) {
            throw new ServiceException("操作任务失败");
        }
        return AjaxResult.success();
    }

    @Transactional
    @Override
    public AjaxResult jTaskComplete(JTaskCompleteDto dto) throws ParseException {
        ResumeDeliver resumeDeliver = getById(dto.getId());
        if (resumeDeliver == null || !resumeDeliver.getEnterpriseId().equals(AppUtil.getUser().getId())) {
            return AjaxResult.error("兼职任务不存在或非法操作");
        }
        resumeDeliver.setIsComplete(dto.getIsComplete());
        resumeDeliver.setRejectMsg(dto.getRejectMsg());
        if (!updateById(resumeDeliver)) {
            throw new ServiceException("操作面试失败");
        }
        //甲方确认完成任务，平台打款到乙方账户余额
        if (resumeDeliver.getIsComplete() == 2) {
            Position position = positionService.getById(resumeDeliver.getPositionId());
            if (position == null) {
                throw new ServiceException("兼职不存在");
            }
            position.setComplete(2);
            if (!positionService.updateById(position)) {
                throw new ServiceException("更新兼职信息失败");
            }

            User user = userService.getById(resumeDeliver.getUserId());
            user.setMoney(user.getMoney().add(new BigDecimal(position.getSalary())));
            if (!userService.updateById(user)) {
                throw new ServiceException("更新用户账户余额失败");
            }
            //添加完成余额入账记录
            Pay pay = new Pay();
            pay.setUserId(user.getId());
            pay.setMoney(new BigDecimal(position.getSalary()));
            pay.setState(1);
            pay.setType(3);
            pay.setTitle(position.getTitle());
            pay.setVersion(System.currentTimeMillis());
            pay.setPositionId(position.getId());
            pay.setNums(StringUtils.generateNumber());
            if (!payService.save(pay)) {
                throw new ServiceException("保存余额入账记录失败,请联系平台");
            }
        }
        sendMessage(resumeDeliver);
        return AjaxResult.success();
    }
}
