local ngx = ngx
local cjson = require "cjson"

local _M = {}

-- 缓存文件路径
local CACHE_ROOT = "/data/cache"

-- 获取缓存文件路径
-- @param string cache_key 缓存键
-- @return string 缓存文件路径
function _M.get_cache_file_path(cache_key)
    local md5 = ngx.md5(cache_key)
    return string.format("%s/%s/%s/%s", CACHE_ROOT, md5:sub(1, 1), md5:sub(2, 2), md5)
end

-- 获取文件大小
-- @param string file_path 文件路径
-- @return number 文件大小（字节）
function _M.get_file_size(file_path)
    local file = io.open(file_path, "r")
    if not file then
        return 0
    end

    local size = file:seek("end")
    file:close()
    return size or 0
end

-- 检查缓存文件是否存在且未过期
-- @param string file_path 缓存文件路径
-- @param number ttl 缓存过期时间
-- @return boolean 缓存是否有效
function _M.check_cache_file(file_path, ttl)
    local file = io.open(file_path, "r")
    if not file then
        ngx.log(ngx.ERR, "failed to open cache file: " .. file_path)
        return false
    end

    local stat = file:seek("end")
    file:close()

    if not stat then
        ngx.log(ngx.ERR, "failed to get cache file size: " .. file_path)
        return false
    end

    return true
end

-- 从缓存文件读取内容
-- @param string file_path 缓存文件路径
-- @return string|nil content 缓存内容
-- @return string|nil err 错误信息
function _M.read_cache_file(file_path)
    local file = io.open(file_path, "r")
    if not file then
        return nil, "failed to open cache file"
    end

    local content = file:read("*a")
    file:close()

    if not content then
        return nil, "failed to read cache file"
    end

    return content
end

-- 写入缓存文件
-- @param string file_path 缓存文件路径
-- @param string content 缓存内容
-- @return boolean ok 是否成功
-- @return string|nil err 错误信息
function _M.write_cache_file(file_path, content)
    -- 确保目录存在
    local dir = file_path:match("(.*/)")
    os.execute("mkdir -p " .. dir)

    local file = io.open(file_path, "w")
    if not file then
        ngx.log(ngx.ERR, "failed to open cache file for writing: " .. file_path)
        return false, "failed to open cache file for writing"
    end

    local ok, err = file:write(content)
    file:close()

    if not ok then
        ngx.log(ngx.ERR, "failed to write cache file: " .. err)
        return false, "failed to write cache file"
    end

    return true
end

-- 处理响应内容
-- @param string content 响应内容
-- @param string content_type 内容类型
-- @return string 处理后的内容
function _M.process_response_content(content, content_type)
    if not content or #content < 1024 or #content > 10 * 1024 * 1024 then
        return content
    end

    -- 检查Content-Type是否需要处理
    local content_types = {
        "text/html", "text/css", "text/javascript", 
        "application/javascript", "application/json", "text/plain"
    }
    
    local need_process = false
    for _, type in ipairs(content_types) do
        if content_type:find(type) then
            need_process = true
            break
        end
    end

    if not need_process then
        return content
    end

    -- 根据客户端支持的压缩方式选择压缩算法
    local accept_encoding = ngx.req.get_headers()["Accept-Encoding"] or ""

    if accept_encoding:find("br") then
        -- 使用brotli压缩
        local brotli = require "brotli"
        local compressed = brotli.compress(content)
        if compressed then
            ngx.header["Content-Encoding"] = "br"
            return compressed
        end
    elseif accept_encoding:find("zstd") then
        -- 使用zstd压缩
        local zstd = require "zstd"
        local compressed = zstd.compress(content)
        if compressed then
            ngx.header["Content-Encoding"] = "zstd"
            return compressed
        end
    elseif accept_encoding:find("gzip") then
        -- 使用gzip压缩
        local gzip = require "ngx.gzip"
        local compressed = gzip.compress(content)
        if compressed then
            ngx.header["Content-Encoding"] = "gzip"
            return compressed
        end
    end

    return content
end

return _M 