package org.linlinjava.jz.admin.service;

import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.google.common.collect.Lists;
import org.linlinjava.jz.admin.util.SecurityHelper;
import org.linlinjava.jz.core.util.DateTimeUtil;
import org.linlinjava.jz.core.util.ResponseUtil;
import org.linlinjava.jz.core.util.StringUtils;
import org.linlinjava.jz.db.domain.*;
import org.linlinjava.jz.db.dto.JzTicketActionDto;
import org.linlinjava.jz.db.service.*;
import org.linlinjava.jz.db.util.RandUtil;
import org.linlinjava.jz.db.util.TicketStatusConstant;
import org.linlinjava.jz.dto.TicketAction;
import org.linlinjava.jz.dto.TicketAllinone;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工单统一处理类
 * 工单咨询类型：各个状态 只能增加 不能减少
 * 工单类型：不能修改
 */
@Service
@Transactional
public class AdminTicketService {

    private final Log logger = LogFactory.getLog(AdminTicketService.class);

    @Autowired
    private JzTicketService ticketService;

    @Autowired
    private JzTicketConsultService consultService;

    @Autowired
    private JzDmTicketConsultTypeService dmTicketConsultTypeService;

    @Autowired
    private JzTicketRelationService relationService;

    @Autowired
    private CustomerClientService customerClientService;

    @Autowired
    private JzTicketActionService actionService;

    @Autowired
    private JzOrderService orderService;

    @Autowired
    private JzSysUserService sysUserService;

    @Autowired
    private JzDmTicketResultService ticketResultService;

    @Autowired
    private JzDepartmentService departmentService;
    @Autowired
    private JzSkillGroupService jzSkillGroupService;
    @Autowired
    private JzSkillGroupUserService jzSkillGroupUserService;

    /**
     * 消息提醒类
     */
    @Autowired
    private JzMallNoticeAdminService noticeAdminService;
    @Autowired
    private JzMallNoticeService noticeService;
    @Autowired
    private JzDmTicketConsultTypeService jzDmTicketConsultTypeService;
    @Autowired
    private JzGoodsCategoryService jzGoodsCategoryService;

    public Object listAll(String mobile, Integer tab, String ticketNo, Integer orderId, Integer ticketType, Integer status, Integer subStatus, String startTime, String endTime, String updateUser, Integer page, Integer limit, String sort, String order) {
        List<JzTicket> tickets = ticketService.querySelective(null, mobile, tab, ticketNo, orderId, ticketType, status, subStatus, startTime, endTime, updateUser, page, limit, sort, order);

        tickets.forEach(item -> {
            if (null != item.getUpdateUser()) {
                item.setUpdateUserName(sysUserService.findAdmin(item.getUpdateUser()).getUserName());
            }
            if (null != item.getSkillGroupId() && item.getSkillGroupId() > 0) {
                item.setSkillGroupName(jzSkillGroupService.findById(item.getSkillGroupId()).getName());
            }
            CustomerClient customerClient = customerClientService.findById(item.getCustomerId());
            if(null !=customerClient) {
            	item.setCustomerTel(customerClient.getTel());
            }//customerClientService.findById(item.getCustomerId()).getTel()
        });

        return ResponseUtil.okList(tickets);
    }


    public Object list(String mobile, Integer tab, String ticketNo, Integer orderId, Integer ticketType, Integer status, Integer subStatus, String startTime, String endTime, String updateUser, Integer page, Integer limit, String sort, String order) {
        List<JzTicket> tickets = ticketService.querySelective(SecurityHelper.getAdminId(), mobile, tab, ticketNo, orderId, ticketType, status, subStatus, startTime, endTime, updateUser, page, limit, sort, order);

        tickets.forEach(item -> {
            if (null != item.getUpdateUser()) {
                item.setUpdateUserName(sysUserService.findAdmin(item.getUpdateUser()).getUserName());
            }
            if (null != item.getSkillGroupId() && item.getSkillGroupId() > 0) {
                item.setSkillGroupName(jzSkillGroupService.findById(item.getSkillGroupId()).getName());
            }
            CustomerClient customerClient = customerClientService.findById(item.getCustomerId());
            if(null !=customerClient) {
            	item.setCustomerTel(customerClient.getTel());
            }
//            item.setCustomerTel(customerClientService.findById(item.getCustomerId()).getTel());
        });

        return ResponseUtil.okList(tickets);
    }


    /**
     * 工单创建
     * 状态有：升级、完成
     *
     * @param ticketAllinone
     * @return
     */
    public Object create(TicketAllinone ticketAllinone) {
        //工单保存
        JzTicket ticket = ticketAllinone.getTicket();
        ticket.setTicketSn(getTicketSno(ticket.getTicketType()));//工单编号
        ticket.setUpdateUser(SecurityHelper.getAdminId());
        ticket.setUpdateTime(LocalDateTime.now());
        ticket.setCreateUser(SecurityHelper.getAdminId());
        ticket.setCreateTime(LocalDateTime.now());
        ticket.setSource("CC");//电访

        if (ticket.getSubstatus().equals(TicketStatusConstant.STATUS_SUB_UPGRADE))//表示升级的工单
        {
            ticket.setHandler(0);//将当前处理人设置为0
        } else {
            ticket.setHandler(SecurityHelper.getAdminId());
        }
        //工单自动生成标题
        StringBuilder title = new StringBuilder();
        if (ticket.getTicketType() == 0) {
            title.append("[咨询]");
        } else {
            title.append("[投诉]");
        }
        int consultIndex = 0;
        if (ticketAllinone.getConsults() != null && ticketAllinone.getConsults().length > 0) {
            for (JzTicketConsult consult : ticketAllinone.getConsults()) {
                consultIndex++;
                JzDmTicketConsultType consultType = dmTicketConsultTypeService.findById(consult.getConsultId());
                if (consultType != null) {
                    title.append(consultType.getName());
                    if (consultIndex < ticketAllinone.getConsults().length) {
                        title.append('-');
                    }
                }
            }
        }
        ticket.setTicketTitle(title.toString());
        //是否创建即完成
        if (ticket.getStatus().equals(TicketStatusConstant.STATUS_COMPLETED)) {
            int count = jzSkillGroupUserService.findSkillGroupIdbyUserId(SecurityHelper.getAdminId());
            ticket.setSkillGroupId(count);
            ticket.setHandleTime(0);
        }

        int ticketId = ticketService.add(ticket);

        //咨询类型
        if (ticketAllinone.getConsults() != null && ticketAllinone.getConsults().length > 0) {
            for (JzTicketConsult consult : ticketAllinone.getConsults()) {
                consult.setTicketId(ticketId);
                consult.setUpdateTime(LocalDateTime.now());
                consult.setUpdateUser(SecurityHelper.getAdminId());
                consult.setCreateTime(LocalDateTime.now());
                consult.setCreateUser(SecurityHelper.getAdminId());
                consult.setDeleted(false);
                consultService.add(consult);
            }
        }

        //关联其他
        if (ticketAllinone.getRelations() != null && ticketAllinone.getRelations().length > 0) {
            for (JzTicketRelation relation : ticketAllinone.getRelations()) {
                relation.setTicketId(ticketId);
                relation.setCreateTime(LocalDateTime.now());
                relation.setCreateUser(SecurityHelper.getAdminId());
                relation.setDeleted(false);
                relationService.add(relation);
            }
        }
        //工单新增时 需要2个处理过程记录
        addAction(ticketId, TicketStatusConstant.STATUS_CREATE, (short) 0, null);
        addAction(ticket, ticketAllinone.getAction().getMemo());

        return ResponseUtil.ok(ticketId);
    }

    /**
     * 工单更新
     * 变更的状态有：待处理、升级、完成
     *
     * @param ticketAllinone
     * @return
     */
    public Object update(TicketAllinone ticketAllinone) {
        //工单保存
        JzTicket ticket = ticketAllinone.getTicket();
        ticket.setUpdateUser(SecurityHelper.getAdminId());
        ticket.setUpdateTime(LocalDateTime.now());
        if (ticket.getSubstatus().equals(TicketStatusConstant.STATUS_SUB_UPGRADE)) {
            ticket.setHandler(0);//将当前处理人设置为0
        } else {
            ticket.setHandler(SecurityHelper.getAdminId());
        }

        ticketService.updateById(ticket);
        //咨询类型 只增不减
        if (ticketAllinone.getConsults() != null && ticketAllinone.getConsults().length > 0) {
            for (JzTicketConsult consult : ticketAllinone.getConsults()) {
                if (consult.getId() != null && consult.getId() > 0) {
                    continue;
                }
                consult.setTicketId(ticket.getId());
                consult.setUpdateTime(LocalDateTime.now());
                consult.setUpdateUser(SecurityHelper.getAdminId());
                consult.setCreateTime(LocalDateTime.now());
                consult.setCreateUser(SecurityHelper.getAdminId());
                consult.setDeleted(false);
                consultService.add(consult);
            }
        }
        //处理过程
        addAction(ticket, ticketAllinone.getAction().getMemo());

        return ResponseUtil.ok();
    }

    /**
     * 工单的升级流转
     *
     * @param action
     * @return
     */
    public Object upgrade(TicketAction action) {
        if (action == null || action.getSkillGroupId() == null) {
            return ResponseUtil.badArgumentValue();
        }

        JzTicket ticket = new JzTicket();
        ticket.setSubstatus(TicketStatusConstant.STATUS_SUB_UPGRADE);
        ticket.setUpdateTime(LocalDateTime.now());
        ticket.setUpdateUser(SecurityHelper.getAdminId());
        ticket.setHandler(0);
        ticket.setSkillGroupId(action.getSkillGroupId());

        JzTicketExample example = new JzTicketExample();
        example.or().andIdEqualTo(action.getId()).andStatusEqualTo(TicketStatusConstant.STATUS_PROCESSING);
        int count = ticketService.updateByExample(ticket, example);

        if (count == 0) {
            return ResponseUtil.badTicketStatus();
        }
        ticket = ticketService.findById(action.getId());

        addAction(ticket, action.getMemo());

        return ResponseUtil.ok();
    }

    /**
     * 工单完成
     *
     * @param action
     * @return
     */
    public Object completed(TicketAction action) {
        if (action == null || action.getSkillGroupId() == null) {
            return ResponseUtil.badArgumentValue();
        }
        JzTicket tempTicket = ticketService.findById(action.getId());

        JzTicket ticket = new JzTicket();
        ticket.setId(action.getId());
        ticket.setSubstatus(TicketStatusConstant.STATUS_SUB_COMPLETED);
        ticket.setStatus(TicketStatusConstant.STATUS_COMPLETED);
        ticket.setUpdateTime(LocalDateTime.now());
        ticket.setUpdateUser(SecurityHelper.getAdminId());
        ticket.setHandler(SecurityHelper.getAdminId());
        ticket.setSkillGroupId(jzSkillGroupUserService.findSkillGroupIdbyUserId(SecurityHelper.getAdminId()));
        ticket.setCreateTime(tempTicket.getCreateTime());
        Duration duration = Duration.between(ticket.getCreateTime(), LocalDateTime.now());
        ticket.setHandleTime((int) duration.getSeconds());//处理时长
        ticket.setResult(action.getResult().shortValue());
        ticket.setResultMemo(action.getMemo());

        JzTicketExample example = new JzTicketExample();
        example.or().andIdEqualTo(action.getId()).andStatusEqualTo(TicketStatusConstant.STATUS_PROCESSING);

        int count = ticketService.updateByExample(ticket, example);
        if (count == 0) {
            return ResponseUtil.badTicketStatus();
        }

        addAction(ticket, action.getMemo());

        return ResponseUtil.ok();
    }

    /**
     * 工单追加备注 增加一个处理过程 但是状态等信息不变
     *
     * @param action
     * @return
     */
    public Object addMemo(TicketAction action) {
        if (action.getId() == null || StringUtils.isEmpty(action.getMemo())) {
            return ResponseUtil.badArgumentValue();
        }

        JzTicket ticket = ticketService.findById(action.getId());
        addAction(ticket, action.getMemo());
        return ResponseUtil.ok();
    }


    /**
     * 已完成工单重新打开
     * 打开的工单 直接归属到当前操作人员
     *
     * @param action
     * @return
     */
    public Object reopen(TicketAction action) {
        if (action == null || action.getId() == null || action.getMemo() == null) {
            return ResponseUtil.badArgumentValue();
        }

        Integer ticketId = action.getId();
        String content = action.getMemo();

        JzTicket ticket = new JzTicket();
        ticket.setId(ticketId);
        ticket.setUpdateTime(LocalDateTime.now());
        ticket.setUpdateUser(SecurityHelper.getAdminId());
        ticket.setStatus(TicketStatusConstant.STATUS_PROCESSING);
        ticket.setSubstatus(TicketStatusConstant.STATUS_SUB_REOPEN);
        ticket.setHandler(SecurityHelper.getAdminId());
        ticket.setSkillGroupId(sysUserService.findSkillGroupIdById(ticket.getHandler()));

        JzTicketExample example = new JzTicketExample();
        example.or().andIdEqualTo(action.getId()).andStatusEqualTo(TicketStatusConstant.STATUS_COMPLETED).andSubstatusEqualTo(TicketStatusConstant.STATUS_SUB_COMPLETED);

        int count = ticketService.updateByExample(ticket, example);
        if (count == 0) {
            return ResponseUtil.badTicketStatus();
        }

        //处理过程
        addAction(ticket, content);
        return ResponseUtil.ok();
    }

    /**
     * 工单驳回
     * 升级的工单返回到上次升级的处理人
     * 取最后一个处理人 赋值给当前工单，并将工单状态修改
     *
     * @param action
     * @return
     */
    public Object reject(TicketAction action) {

        //工单最后处理人
        Integer lastHandler = actionService.queryLastHandler(action.getId());
        if (lastHandler == 0) {
            return ResponseUtil.badArgument();
        }

        //构造一个ticket
        JzTicket ticket = new JzTicket();
        ticket.setId(action.getId());
        ticket.setUpdateTime(LocalDateTime.now());
        ticket.setUpdateUser(SecurityHelper.getAdminId());
        ticket.setStatus(TicketStatusConstant.STATUS_PROCESSING);
        ticket.setSubstatus(TicketStatusConstant.STATUS_SUB_REJECTED);
        ticket.setHandler(lastHandler);
        ticket.setSkillGroupId(sysUserService.findSkillGroupIdById(ticket.getHandler()));

        JzTicketExample example = new JzTicketExample();
        example.or().andIdEqualTo(action.getId()).andStatusEqualTo(TicketStatusConstant.STATUS_PROCESSING).andSubstatusEqualTo(TicketStatusConstant.STATUS_SUB_UPGRADE);

        int count = ticketService.updateByExample(ticket, example);
        if (count < 1) {
            return ResponseUtil.badTicketStatus();
        }

        //处理过程
        addAction(ticket, action.getMemo());

        JzTicket tempTicket = ticketService.findById(ticket.getId());
        //添加通知
        addNoticeAssigned(lastHandler, tempTicket.getTicketSn(), ticket.getId(), "被驳回", TicketStatusConstant.getStatusDes(TicketStatusConstant.STATUS_PROCESSING, TicketStatusConstant.STATUS_SUB_REJECTED));

        return ResponseUtil.ok();
    }


    /**
     * 添加电访、话务、订单和工单关系
     *
     * @param relation
     * @return
     */
    public Object addRelation(JzTicketRelation relation) {
        relation.setCreateUser(SecurityHelper.getAdminId());
        relation.setCreateTime(LocalDateTime.now());
        relationService.add(relation);
        return ResponseUtil.ok();
    }

    /**
     * 删除一个绑定关系
     *
     * @param relation_id
     * @return
     */
    public Object removeRelation(int relation_id) {
        JzTicketRelation relation = relationService.findById(relation_id);
        relation.setDeleted(true);
        relation.setUpdateTime(LocalDateTime.now());
        relation.setUpdateUser(SecurityHelper.getAdminId());
        relationService.updateById(relation);
        return ResponseUtil.ok();
    }

    /**
     * 工单明细
     * 返回值包括5部分：客户信息、工单、工单咨询类型、工单处理过程、工单关联信息
     *
     * @param id
     * @return
     */
    public Object detail(Integer id) {
        JzTicket ticket = ticketService.findById(id);
        if (ticket == null) {
            return ResponseUtil.badArgument();
        }

        //归属技能组
        if (null != ticket.getSkillGroupId()) {
            JzSkillGroup skillGroup = jzSkillGroupService.findById(ticket.getSkillGroupId());
            ticket.setSkillGroupName(null != skillGroup ? skillGroup.getName() : "");
        }

        //处理时长
        if (!ticket.getStatus().equals(TicketStatusConstant.STATUS_COMPLETED)) {
            Duration duration = Duration.between(ticket.getCreateTime(), LocalDateTime.now());
            ticket.setHandleTime((int) duration.getSeconds());
        }

        //投诉产品
        if (ticket.getGoodsId() != null && ticket.getGoodsId() > 0) {
            JzGoodsCategory jzGoodsCategory = jzGoodsCategoryService.selectById(ticket.getGoodsId());
            if (null != jzGoodsCategory) {
                JzGoodsCategory jzGoodsCategory1 = jzGoodsCategoryService.selectById(jzGoodsCategory.getPid());
                ticket.setProductName(jzGoodsCategory1.getName() + "->" + jzGoodsCategory.getName());
            }
        }

        //最后处理人
        SysUser sysUser = sysUserService.findAdmin(ticket.getUpdateUser());
        ticket.setUpdateUserName(null != sysUser ? sysUser.getUserName() : "");

        CustomerClient customerClient = customerClientService.findById(ticket.getCustomerId());
        //咨询内容
        List<JzTicketConsult> consultList = consultService.queryByTocketId(id);
        List<String> list = Lists.newArrayList();
        consultList.forEach(item1 -> {
            JzDmTicketConsultType jzDmTicketConsultType = jzDmTicketConsultTypeService.queryById(item1.getConsultId());
            if(null!=jzDmTicketConsultType) {
            	list.add(jzDmTicketConsultType.getPath());
            }
        });

//        List<JzTicketAction> actions = actionService.queryByTocketId(id);
        //工单详情
        List<JzTicketActionDto> actions = actionService.selectByTicketId(id);

        List<JzTicketRelation> relations = relationService.queryByTocketId(id);
        JzOrder order = null;
        if (ticket.getOrderId() != null && ticket.getOrderId() > 0) {
            order = orderService.findByIdColumn(ticket.getOrderId());
        }

        Map<String, Object> data = new HashMap<>();

        data.put("ticket", ticket);
        data.put("customer", customerClient);
        data.put("consults", list);
        data.put("relations", relations);
        data.put("actions", actions);
        data.put("order", order);

        return ResponseUtil.ok(data);
    }


    /**
     * 工单作废
     * 暂时隐藏--不启用
     *
     * @param id
     * @param content
     * @return
     */
    public Object deleted(Integer id, String content) {
        JzTicket ticket = ticketService.findById(id);
        if (ticket == null) {
            return ResponseUtil.badArgument();
        }

        ticket.setStatus(TicketStatusConstant.STATUS_DELETED);
        ticket.setSubstatus(TicketStatusConstant.STATUS_SUB_DELETED);
        ticket.setUpdateUser(SecurityHelper.getAdminId());
        ticketService.deleteById(ticket);
        //新增处理过程
        addAction(id, TicketStatusConstant.STATUS_DELETED, TicketStatusConstant.STATUS_SUB_DELETED, content);

        return ResponseUtil.ok();
    }

    /**
     * 工单处理结果枚举类 前端使用
     *
     * @return
     */
    public Object ticketResult() {
        return ResponseUtil.ok(ticketResultService.queryAll());
    }


    /**
     * 增加一个工单处理过程记录
     *
     * @param content
     */
    void addAction(JzTicket ticket, String content) {
        //处理过程 --工单新增时 有2个处理过程 1，创建 2，工单实际流转状态
        addAction(ticket.getId(), ticket.getStatus(), ticket.getSubstatus(), content);
    }

    void addAction(Integer ticketId, short status, short status_sub, String content) {
        JzTicketAction action = new JzTicketAction();
        action.setTicketId(ticketId);
        action.setContent(content);
        action.setCreateTime(LocalDateTime.now());
        action.setCreateUser(SecurityHelper.getAdminId());
        action.setStatus(status);
        action.setStatusSub(status_sub);
        action.setStatusDes(TicketStatusConstant.getStatusDes(status, status_sub));
        actionService.add(action);
    }

    /**
     * 随机生成工单编号 长度12 ，年月开头 6位随机
     *
     * @return
     */
    String getTicketSno(int type) {
        String pre = type == 0 ? "Z" : "T";
        String sn = pre + DateTimeUtil.localDateFormat(LocalDateTime.now(), "yyyyMM") + RandUtil.getRandomNum(6);
        while (true) {
            JzTicket jzTicket = ticketService.findBySn(sn);
            if (jzTicket != null) {
                sn = pre + DateTimeUtil.localDateFormat(LocalDateTime.now(), "yyyyMM") + RandUtil.getRandomNum(6);
            } else {
                return sn;
            }
        }
    }

    //创建通知
    int addNotice(String ticketNo, int tictetId, String action, String status) {
        JzMallNotice notice = new JzMallNotice();
        notice.setAddTime(LocalDateTime.now());
        notice.setAdminId(0);
        notice.setDeleted(false);
        notice.setTitle("您有待处理工单，编号：" + ticketNo + action + ",请及时处理");

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("工单：");
        stringBuilder.append(ticketNo);
        stringBuilder.append("<br/>");

        stringBuilder.append("状态：");
        stringBuilder.append(status);
        stringBuilder.append("<br/>");

//        stringBuilder.append("事件描述：");
//        stringBuilder.append("状态：");
//        stringBuilder.append("<br/>");


        stringBuilder.append("操作人：");
        stringBuilder.append(SecurityHelper.getAdminName());

        //处理按钮
//        stringBuilder.append("<router-link to=\"/home\">首页</router-link>");

        notice.setContent(stringBuilder.toString());
        noticeService.add(notice);
        return notice.getId();
    }

    /**
     * 分配通知
     *
     * @param adminId
     */
    @Async
    void addNoticeAssigned(int adminId, String ticketNo, int tictetId, String action, String status) {

        int id = addNotice(ticketNo, tictetId, action, status);
        //先创建通知 然后分配通知
        JzMallNoticeAdmin noticeAdmin = new JzMallNoticeAdmin();
        noticeAdmin.setAddTime(LocalDateTime.now());
        noticeAdmin.setAdminId(adminId);
        noticeAdmin.setNoticeId(id);
        noticeAdmin.setNoticeTitle("您有待处理工单，工单号：" + ticketNo + action + ",请及时处理");
        noticeAdmin.setDeleted(false);
        noticeAdminService.add(noticeAdmin);
    }

    /**
     * 通过手机号查询工单
     *
     * @param mobile
     * @return
     */
    public Object selectTicketByMobile(String mobile) {
        List<JzTicket> tickets = ticketService.selectTicketByMobile(mobile);

        tickets.forEach(item -> {
            if (null != item.getUpdateUser()) {
                item.setUpdateUserName(sysUserService.findAdmin(item.getUpdateUser()).getUserName());
            }
        });
        return ResponseUtil.ok(tickets);
    }


    /**
     * @param tab    1:我的工单 2：24小时工单 3：48小时 4：已完结 5 ：处理中
     * @param userId 用户ID
     * @return
     */
    public long selectCountByExample(Integer tab, Integer userId) {
        return ticketService.count(tab, userId);
    }
}
