---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by hartnett.
--- DateTime: 2019/11/10 20:34
---

local ngx = require("ngx")
local table = table
local string = require("string")
local math = require("math")
local uuid = require('resty.jit-uuid')

local core = require("apisix.core")
local redis = require("apisix.core.redis")
local send_notice = require("apisix.plugins.exchange-ews.send_notice")
local device_manager = require("apisix.plugins.exchange-ews.device_manager")


-- 生成激活码
local function generate_active_code(username, device_id)
    device_id = device_id or ngx.now()
    username = username or ngx.now()
    uuid.seed()
    math.randomseed(tostring(ngx.now()):reverse():sub(1, 7))
    local t = math.random()
    local code = ngx.md5(t .. uuid() .. username .. device_id .. ngx.now())
    local active_code = string.sub(code, 10, 18)
    return active_code
end


-- 判断某设备id的激活码是否生成过
local function exist_active_code_flag(username, ip)
    local key = string.format("EWS_CODEF_%s", username)
    local has = false
    local code = ""

    local redis_cli = redis.new()
    local res = redis_cli:get(key)

    if res ~= nil and type(res) == "string" then
        code = res
        has = true
    end

    return has, code
end

-- 删除激活码的标志
local function del_active_code_flag(username, ip)
    local key = string.format("EWS_CODEF_%s", username)
    local redis_cli = redis:new()
    redis_cli:del(key)
end

-- 获取激活码的内容
local function get_value_by_code(code)
    local key = string.format("EWS_CODE_%s", code)
    local username = ""
    local ip = ""
    local state = -1
    local client_type = ""

    local redis_cli = redis.new()

    local res, err = redis_cli:hmget(key, "username", "ip", "state", "client_type")
    if err == nil and res ~= nil then
        if type(res[1]) == "string" then
            username = res[1]
            ip = res[2]
            state = res[3]
            client_type = res[4]
        end
    end

    return username, ip, tonumber(state), client_type
end

-- 设置验证码的标识，判断是否生成过验证码，12小时后失效
local function set_active_code_flag(username, ip, code)
    local key = string.format("EWS_CODEF_%s", username)
    local redis_cli = redis.new()

    redis_cli:set(key, code)
    redis_cli:expire(key, 60 * 60 * 12)
end

-- 设置验证码的值及超时时间，0表示未使用
local function _set_active_code(code, username, ip, client_type, iplist)
    local key = string.format("EWS_CODE_%s", code)
    local redis_cli = redis:new()
    local ips = table.concat(iplist, ",")
    redis_cli:hmset(key, "username", username, "ip", ip, "state", 0, "client_type", client_type, "iplist", ips)
    redis_cli:expire(key, 3600 * 12)
end

-- 激活码使用后的有效期为30分钟，2表示已经使用
local function set_active_code_state(code, username, ip)
    local key = string.format("EWS_CODE_%s", code)
    local redis_cli = redis:new()
    redis_cli:hmset(key, "username", username, "ip", ip, "state", 2)
    redis_cli:expire(key, 60 * 30)
    -- 使用后重置短信限制策略
    send_notice.reset_status(username, ip)
end


-- 删除验证码
local function remove_code(code)
    local key = string.format("EWS_CODE_%s", code)
    local redis_cli = redis.new()
    redis_cli:del(key)
end


-- 激活码保存到redis中，有效期为8小时，多次生成的话，只有最后一次的有效
local function set_active_code(username, ip, user_agent, iplist)
    core.log.warn(string.format("username: %s, ip：%s, user_agent: %s, ip_list: %s",
            username,
            ip,
            username,
            iplist
    ))

    local code = generate_active_code(username, user_agent)

    -- 判断是否进行了激活操作
    local has, code1 = exist_active_code_flag(username, ip)
    if not has then
        set_active_code_flag(username, ip, code)
        _set_active_code(code, username, ip, user_agent, iplist)
    else
        -- 如果已生成过激活码，就用老激活码
        code = code1
        _set_active_code(code, username, ip, user_agent, iplist)
    end
    return code
end

-- 设备激活状态设置，有效期为60秒
local function set_ews_active_status(username, remote_ip)
    local key = string.format("ews_active_%s", username)

    local redis_cli = redis.new()
    redis_cli:set(key, remote_ip)
    redis_cli:expire(key, 60)
end

-- 判断设备是否处于1分钟内激活过
local function exist_ews_active(username, remote_ip)
    local redis_cli = redis.new()

    local result = false
    local key = string.format("ews_active_%s", username)

    local res, err = redis_cli:get(key)
    if res ~= nil and type(res) == "string" and #res >= 7 then
        result = true
    end

    return result
end

-- ews激活流程
local function do_ews_active(user_agent, client_type, username, remote_ip, iplist)
    ngx.ctx.is_not_activated = true

    -- 判断是否在一分钟之内激活过
    if exist_ews_active(username, remote_ip) then
        core.log.warn("激活频率太快，退出")
        ngx.exit(ngx.HTTP_OK)
    else
        set_ews_active_status(username, remote_ip)
        local code = set_active_code(username, remote_ip, user_agent, iplist)
        local send_status = send_notice.send_ews_active_code(username, user_agent, client_type, remote_ip, iplist, code)
        if send_status then
            -- 删除激活码标志，防止在激活短信中重复发相同的激活码
            del_active_code_flag(username, remote_ip)
        end

        device_manager.add_ews_address(username, remote_ip, 1, 1, client_type)
    end
end

local _M = {
    generate_active_code = generate_active_code,
    set_active_code = set_active_code,

    --激活码发送后就删除
    del_active_code_flag = del_active_code_flag,
    _set_active_code = _set_active_code,
    set_active_code_state = set_active_code_state,
    do_ews_active = do_ews_active,
    remove_code = remove_code,
}

return _M
