package com.ruoyi.web.controller.system;

import java.util.*;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.ruoyi.cc.domain.CcExtNum;
import com.ruoyi.cc.domain.CcGateways;
import com.ruoyi.cc.domain.SysDivisionData;
import com.ruoyi.cc.service.ICcExtNumService;
import com.ruoyi.cc.service.ICcGatewaysService;
import com.ruoyi.cc.service.ICcParamsService;
import com.ruoyi.cc.service.ISysDivisionDataService;
import com.ruoyi.common.config.ServerConfig;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
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.ResponseBody;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.framework.shiro.service.SysPasswordService;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysMenuService;
import org.springframework.web.multipart.MultipartFile;

/**
 * 首页 业务处理
 * 
 * @author ruoyi
 */
@Controller
public class SysIndexController extends BaseController
{
    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private ICcExtNumService ccExtNumService;

    @Autowired
    private ICcGatewaysService ccGatewaysService;

    @Autowired
    private ICcParamsService ccParamsService;

    @Autowired
    private ServerConfig serverConfig;

    private String scriptServer;
    private String scriptPort;

    /**
     * 系统包版本
     */
    @Value("${sysconfig.sysVersion}")
    private String sysVersion;

    // 系统首页
    @GetMapping("/index")
    public String index(ModelMap mmap)
    {
        // 取身份信息
        SysUser user = getSysUser();
        // 根据用户id取出菜单
        List<SysMenu> menus = menuService.selectMenusByUser(user);
        mmap.put("menus", menus);
        mmap.put("user", user);
        mmap.put("sideTheme", configService.selectConfigByKey("sys.index.sideTheme"));
        mmap.put("skinName", configService.selectConfigByKey("sys.index.skinName"));
        Boolean footer = Convert.toBool(configService.selectConfigByKey("sys.index.footer"), true);
        Boolean tagsView = Convert.toBool(configService.selectConfigByKey("sys.index.tagsView"), true);
        mmap.put("footer", footer);
        mmap.put("tagsView", tagsView);
        mmap.put("mainClass", contentMainClass(footer, tagsView));
        mmap.put("copyrightYear", RuoYiConfig.getCopyrightYear());
        mmap.put("sysVersion", sysVersion);
        mmap.put("isLocalDebug", RuoYiConfig.isLocalDebug());
        mmap.put("localRemoteHost", RuoYiConfig.getLocalRemoteHost());
        if (user.getLoginName().equals("admin")) {
            mmap.put("demoEnabled", RuoYiConfig.isDemoEnabled());
        } else {
            mmap.put("demoEnabled", false);
        }
        mmap.put("isDefaultModifyPwd", initPasswordIsModify(user.getPwdUpdateDate()));
        mmap.put("isPasswordExpired", passwordIsExpiration(user.getPwdUpdateDate()));
        mmap.put("isMobile", ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")));

        // logo
        String logoPath = user.getLogo();
        if (StringUtils.isBlank(logoPath)) {
            logoPath = configService.selectConfigByKey("sys.logo", "/img/logo.png");
        }
        mmap.put("logoPath", logoPath);

        // 菜单导航显示风格
        String menuStyle = configService.selectConfigByKey("sys.index.menuStyle");
        // 移动端，默认使左侧导航菜单，否则取默认配置
        String indexStyle = ServletUtils.checkAgentIsMobile(ServletUtils.getRequest().getHeader("User-Agent")) ? "index" : menuStyle;

        // 优先Cookie配置导航菜单
        Cookie[] cookies = ServletUtils.getRequest().getCookies();
        for (Cookie cookie : cookies)
        {
            if (StringUtils.isNotEmpty(cookie.getName()) && "nav-style".equalsIgnoreCase(cookie.getName()))
            {
                indexStyle = cookie.getValue();
                break;
            }
        }
        String webIndex = "topnav".equalsIgnoreCase(indexStyle) ? "index-topnav" : "index";
        return webIndex;
    }

    // 锁定屏幕
    @GetMapping("/lockscreen")
    public String lockscreen(ModelMap mmap)
    {
        mmap.put("user", getSysUser());
        ServletUtils.getSession().setAttribute(ShiroConstants.LOCK_SCREEN, true);
        return "lock";
    }

    // 解锁屏幕
    @PostMapping("/unlockscreen")
    @ResponseBody
    public AjaxResult unlockscreen(String password)
    {
        SysUser user = getSysUser();
        if (StringUtils.isNull(user))
        {
            return AjaxResult.error("服务器超时，请重新登录");
        }
        if (passwordService.matches(user, password))
        {
            ServletUtils.getSession().removeAttribute(ShiroConstants.LOCK_SCREEN);
            return AjaxResult.success();
        }
        return AjaxResult.error("密码不正确，请重新输入。");
    }

    // 切换主题
    @GetMapping("/system/switchSkin")
    public String switchSkin()
    {
        return "skin";
    }

    // 切换菜单
    @GetMapping("/system/menuStyle/{style}")
    public void menuStyle(@PathVariable String style, HttpServletResponse response)
    {
        CookieUtils.setCookie(response, "nav-style", style);
    }

    // system main / agent workbench (embed=1 supported)
    @GetMapping("/system/main")
    public String main(ModelMap mmap)
    {
        mmap.put("version", RuoYiConfig.getVersion());
        boolean embed = "1".equals(ServletUtils.getParameter("embed"));
        mmap.put("embedMode", embed);
        mmap.put("isLocalDebug", RuoYiConfig.isLocalDebug());
        mmap.put("localRemoteHost", RuoYiConfig.getLocalRemoteHost());

        // current user
        SysUser currentUser = ShiroUtils.getSysUser();
        if (currentUser == null)
        {
            if (embed)
            {
                mmap.put("errorMsg", "登录会话无效，请重新外呼登录");
                mmap.put("errorCode", "NO_SESSION");
                return "error/embedWorkbench";
            }
            return "redirect:/login";
        }
        // extension number
        CcExtNum ccExtNum = ccExtNumService.selectCcExtNumByUserCodeTwo(currentUser.getLoginName());
        if (ccExtNum == null || ccExtNum.getExtNum() == null) {
            // embed 下禁止 redirect:/login（会再次触发 LOGIN_READY，被 HIS 误判为 Cookie 回弹）
            if (embed)
            {
                mmap.put("errorMsg", "未绑定分机号，请联系系统管理员");
                mmap.put("errorCode", "NO_EXT");
                return "error/embedWorkbench";
            }
            return "redirect:/login";
        }

        String extnum = ccExtNum.getExtNum().toString();
        String opnum = ccExtNum.getUserCode();
        String groupId = (String) CacheUtils.get("groupId-" + currentUser.getLoginName());
        if (StringUtils.isBlank(groupId)) {
            groupId = "1";
        }
        String skillLevel = "9";
        String projectId = "1";
        String loginToken = ccExtNumService.createToken(extnum, opnum, groupId, skillLevel, projectId);

        // myGateway from login; always restrict to purposes 1/3 (exclude 2 outbound tasks)
        String myGateway = (String) CacheUtils.get("myGateway-" + currentUser.getLoginName());
        CcGateways ccGatewaysVo = new CcGateways();
        Map<String, Object> params = new HashMap<>();
        params.put("purposes", Arrays.asList(1, 3));
        ccGatewaysVo.setParams(params);
        if (StringUtils.isNotBlank(myGateway)) {
            List<Long> gatewayIds = Arrays.stream(myGateway.split(","))
                    .filter(StringUtils::isNotBlank)
                    .map(String::trim)
                    .map(Long::parseLong)
                    .collect(java.util.stream.Collectors.toList());
            ccGatewaysVo.setGatewayIds(gatewayIds);
        }
        List<CcGateways> gatewaysList = ccGatewaysService.selectCcGatewaysList(ccGatewaysVo);
        List<JSONObject> gatewayList = new ArrayList<>();
        for (CcGateways ccGateways: gatewaysList) {
            JSONObject configGateway = new JSONObject();
            configGateway.put("uuid", ccGateways.getId().toString());
            configGateway.put("updateTime", ccGateways.getUpdateTime());
            configGateway.put("gatewayAddr", ccGateways.getGwAddr());
            configGateway.put("callerNumber", ccGateways.getCaller());
            configGateway.put("calleePrefix", ccGateways.getCalleePrefix());
            configGateway.put("callProfile", ccGateways.getProfileName());
            configGateway.put("priority", ccGateways.getPriority());
            configGateway.put("concurrency", ccGateways.getMaxConcurrency());
            configGateway.put("register", ccGateways.getRegister());
            configGateway.put("authUsername", ccGateways.getAuthUsername());
            configGateway.put("audioCodec", ccGateways.getCodec());
            configGateway.put("gwName", ccGateways.getGwName());
            gatewayList.add(configGateway);
        }
        JSONObject callConfig = new JSONObject();

        scriptServer = ccParamsService.getParamValueByCode("call-center-server-ip-addr", "");
        scriptPort = ccParamsService.getParamValueByCode("call-center-websocket-port", "");

        callConfig.put("scriptServer", scriptServer);
        callConfig.put("scriptPort", scriptPort);
        callConfig.put("loginToken", loginToken);
        callConfig.put("gatewayList", gatewayList);
        callConfig.put("extNum", extnum);
        callConfig.put("opNum", opnum);
        callConfig.put("myGateway", myGateway);
        mmap.put("callConfig", callConfig);
        String autoFree = ccParamsService.getParamValueByCode("phone-bar-free-auto", "false");
        mmap.put("autoFree", Boolean.valueOf(autoFree));

        return "main";
    }

    // content-main class
    public String contentMainClass(Boolean footer, Boolean tagsView)
    {
        if (!footer && !tagsView)
        {
            return "tagsview-footer-hide";
        }
        else if (!footer)
        {
            return "footer-hide";
        }
        else if (!tagsView)
        {
            return "tagsview-hide";
        }
        return StringUtils.EMPTY;
    }

    // 检查初始密码是否提醒修改
    public boolean initPasswordIsModify(Date pwdUpdateDate)
    {
        Integer initPasswordModify = Convert.toInt(configService.selectConfigByKey("sys.account.initPasswordModify"));
        return initPasswordModify != null && initPasswordModify == 1 && pwdUpdateDate == null;
    }

    // 检查密码是否过期
    public boolean passwordIsExpiration(Date pwdUpdateDate)
    {
        Integer passwordValidateDays = Convert.toInt(configService.selectConfigByKey("sys.account.passwordValidateDays"));
        if (passwordValidateDays != null && passwordValidateDays > 0)
        {
            if (StringUtils.isNull(pwdUpdateDate))
            {
                // 如果从未修改过初始密码，直接提醒过期
                return true;
            }
            Date nowDate = DateUtils.getNowDate();
            return DateUtils.differentDaysByMillisecond(nowDate, pwdUpdateDate) > passwordValidateDays;
        }
        return false;
    }

    @PostMapping("/uploadLogo")
    @ResponseBody
    public AjaxResult uploadLogo(MultipartFile file) throws Exception
    {
        try
        {
            // 上传文件路径
            String filePath = RuoYiConfig.getUploadPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;
            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            configService.updateConfigByKey("sys.logo", url);
            return ajax;
        }
        catch (Exception e)
        {
            return AjaxResult.error(e.getMessage());
        }
    }
}
