using FiniteDifferences
using DataFrames
using CategoricalArrays
using CSV
using MixedModels
using StatsPlots
using Printf
using Combinatorics
function shapley_regression(df, lhs, p)
    Δr² = similar(p, Float64)
    Δr² .= 0
    for ipick ∈ eachindex(p)
        p_pick = p[ipick]
        p_rest = filter(x -> x != p_pick, p)
        r_terms = term(1) + (term(1) | term(:seq_type)) + (term(1) | term(:seq_name)) + (term(1) | term(:ROI))
        for nterms = 0:length(p_rest)
            weight = 1 / length(combinations(p_rest, nterms)) / (length(p_rest) + 1)
            for combination ∈ combinations(p_rest, nterms)
                rhs = combination == Symbol[] ? r_terms : sum(t -> term(t), combination) + r_terms
                r²_rest = _r2(df, term(lhs), rhs)
                rhs += term(p_pick)
                r²_pick = _r2(df, term(lhs), rhs)
                Δr²[ipick] += weight * (r²_pick - r²_rest)
            end
        end
    end
    return Δr²
end
function _r2(df, lhs, rhs)
    model = fit(MixedModel, lhs ~ rhs, df)
    fixedeffects = Symbol.(rhs[collect(typeof.(rhs) .== Term)])
    σ²_fixed = isempty(fixedeffects) ? 0 : var(sum(param -> model.βs[param] .* df[!, param], fixedeffects); corrected=false)
    σ²_ROI = model.σs[:ROI][1]^2
    σ²_seqname = model.σs[:seq_name][1]^2
    σ²_seqtype = model.σs[:seq_type][1]^2
    σ²_ϵ = model.σ^2
    σ²_all = σ²_fixed + σ²_ROI + σ²_seqtype + σ²_seqname + σ²_ϵ
    r² = σ²_fixed / σ²_all
    return r²
end
function get_main_path()
    path_parts = splitpath(pwd())
    i_docs = findfirst(==("docs"), path_parts)
    main_path = i_docs === nothing ? pwd() : joinpath(path_parts[1:i_docs-1]...)
    return main_path
end