--- Unit tests for assume.lua
-- Tests pure functions that don't depend on external state

-- Add the parent directory to the Lua path so we can load the modules
local script_path = debug.getinfo(1, "S").source:sub(2)
local plugin_dir = script_path:match("(.*/)")  -- Get directory of this file
plugin_dir = plugin_dir:gsub("spec/$", "")  -- Go up to plugin root

-- Add to package.path
package.path = plugin_dir .. "?.lua;" .. plugin_dir .. "?/init.lua;" .. package.path

-- Mock dependencies before loading the module
_G.kong = {
  log = {
    notice = function() end,
    err = function() end,
  }
}

_G.ngx = {
  escape_uri = function(str)
    return str
  end
}

-- Mock resty.lock
package.loaded["resty.lock"] = {
  new = function()
    return {
      lock = function() return true end,
      unlock = function() return true end,
    }
  end
}

-- Mock resty.lrucache
package.loaded["resty.lrucache"] = {
  new = function()
    local cache = {}
    return {
      get = function(self, key) return cache[key] end,
      set = function(self, key, value) cache[key] = value end,
      delete = function(self, key) cache[key] = nil end,
      flush_all = function(self) cache = {} end,
    }
  end
}

package.loaded["resty.http"] = {}
package.loaded["kong.plugins.o11y-proxy.http_client"] = {
  new = function()
    return {
      set_timeout = function() end,
      request_uri = function() return {status = 200, body = ""}, nil end,
    }
  end
}
package.loaded["kong.plugins.o11y-proxy.irsa"] = {
  new = function()
    return {
      get_credentials = function()
        return {
          access_key_id = "test_access_key",
          secret_access_key = "test_secret_key",
          session_token = "test_session_token",
        }
      end
    }
  end
}
package.loaded["kong.plugins.o11y-proxy.utils"] = {
  parse_iso8601 = function(date_str)
    if date_str and date_str ~= "" then
      return os.time() + 3600
    end
    return nil
  end
}
package.loaded["kong.plugins.o11y-proxy.aws_signer"] = {
  sign_request = function()
    return {}, nil
  end
}

local assume = dofile(plugin_dir .. "assume.lua")

describe("assume.lua", function()
  
  describe("Assume.new", function()
    it("should create a new Assume instance with required parameters", function()
      local assume_obj = assume.new({
        role_arn = "arn:aws:iam::123456789012:role/TestRole",
      })
      
      assert.is_not_nil(assume_obj)
      assert.equals("arn:aws:iam::123456789012:role/TestRole", assume_obj.role_arn)
      assert.equals("kong-plugin-session-assume", assume_obj.session_name)
      assert.equals("us-east-1", assume_obj.region)
    end)
    
    it("should use custom session_name when provided", function()
      local assume_obj = assume.new({
        role_arn = "arn:aws:iam::123456789012:role/TestRole",
        session_name = "custom-session-name",
      })
      
      assert.equals("custom-session-name", assume_obj.session_name)
    end)
    
    it("should use custom region when provided", function()
      local assume_obj = assume.new({
        role_arn = "arn:aws:iam::123456789012:role/TestRole",
        region = "us-west-2",
      })
      
      assert.equals("us-west-2", assume_obj.region)
    end)
    
    it("should error when role_arn is not provided", function()
      assert.has_error(function()
        assume.new({})
      end, "role_arn must be specified")
    end)
    
    it("should error when role_arn is empty string", function()
      assert.has_error(function()
        assume.new({ role_arn = "" })
      end, "role_arn must be specified")
    end)
    
    it("should store external_id when provided", function()
      local assume_obj = assume.new({
        role_arn = "arn:aws:iam::123456789012:role/TestRole",
        external_id = "unique-external-id-123",
      })
      
      assert.equals("unique-external-id-123", assume_obj.external_id)
    end)
  end)
  
  describe("Assume:clear_cache", function()
    it("should clear the credentials cache", function()
      local assume_obj = assume.new({
        role_arn = "arn:aws:iam::123456789012:role/TestRole",
      })
      
      -- This should not error
      assert.has_no_error(function()
        assume_obj:clear_cache()
      end)
    end)
  end)
end)
