local helpers = require "spec.helpers"
local md5 = require "resty.md5"
local str = require "resty.string"
local cjson_safe = require "cjson.safe"

local REDIS_HOST = helpers.redis_host
local REDIS_PORT = helpers.redis_port
local REDIS_PASSWORD = ""
local REDIS_DATABASE = 1

local function init_dependency()
    local redis = require "resty.redis"
    local red = redis:new()
    red:set_timeout(2000)
    local ok, err = red:connect(REDIS_HOST, REDIS_PORT)
    if not ok then
        error("failed to connect to Redis: " .. err)
    end

    if REDIS_PASSWORD and REDIS_PASSWORD ~= "" then
        local ok, err = red:auth(REDIS_PASSWORD)
        if not ok then
            error("failed to connect to Redis: " .. err)
        end
    end

    local ok, err = red:select(REDIS_DATABASE)
    if not ok then
        error("failed to change Redis database: " .. err)
    end

    local ok, err = red:set("dbaas:account:api_keys:abc",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[\"0.0.0.0/0\"]}")
    if not ok then
        error("failed to set `abc` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc1",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[\"0.0.0.0/32\"]}")
    if not ok then
        error("failed to set `abc1` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc2",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[\"127.0.0.0/8\", \"192.0.0.0/8\"]}")
    if not ok then
        error("failed to set `abc2` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc3",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\", \"cidrs\":[]}")
    if not ok then
        error("failed to set `abc3` api keys: " .. err)
    end
    local ok, err = red:set("dbaas:account:api_keys:abc4",
                            "{\"private_key\":\"895e6c10bad41ad3adc353baa50138cd\"}")
    if not ok then
        error("failed to set `abc4` api keys: " .. err)
    end
    helpers.setenv("SECRET_AES_256_KEY", "12345678901234561234567890123456")
    helpers.setenv("SECRET_AES_256_IV", "1234567890123456")

    red:close()
end

for _, strategy in helpers.each_strategy() do
    describe("Plugin: custom-basic-auth-and-custom-cors [#" .. strategy .. "]",
             function()
        local proxy_client
        lazy_setup(function()
            init_dependency()

            local bp = helpers.get_db_utils(strategy,
                                            {"routes", "services", "plugins"})

            local service1 = bp.services:insert{
                protocol = "http",
                host = helpers.mock_upstream_host,
                port = helpers.mock_upstream_port
            }

            local route1 = bp.routes:insert{
                protocols = {"http", "https"},
                hosts = {"test1.com"},
                service = service1
            }

            bp.plugins:insert{
                route = {id = route1.id},
                name = "custom-basic-auth",
                config = {
                    nonce_key = "1234567890123456",
                    nonce_iv = "1234567890123456",
                    redis_host = REDIS_HOST,
                    redis_database = REDIS_DATABASE
                }
            }
            
            bp.plugins:insert{route = {id = route1.id}, name = "bearer-token-auth"}

            bp.plugins:insert{
                route = {id = route1.id},
                name = "custom-cors",
                config = {}
            }

            assert(helpers.start_kong({
                database = strategy,
                nginx_conf = "spec/fixtures/custom_nginx.template",
                plugins = "custom-cors,custom-basic-auth,bearer-token-auth"
            }))
        end)

        lazy_teardown(function()
            helpers.stop_kong()
        end)

        before_each(function()
            proxy_client = helpers.proxy_client()
        end)

        after_each(function()
            if proxy_client then
                proxy_client:close()
            end
        end)

        describe("Test With CORS Plugin", function()
            it("OPTIONS returns 204", function()
                local r = assert(proxy_client:send({
                    method = "OPTIONS",
                    path = "/status/200",
                    headers = {
                        ["Host"] = "test1.com",
                        ["Origin"] = "tidbcloud.com",
                        ["Access-Control-Request-Method"] = "GET"
                    }
                }))
                assert.res_status(204, r)
            end)
        end)
    end)
end
