function [W, R, M, N, E, opt_gap] = R_DLRR(X, D, Dt, alpha, lambda, transformRow, transformCol, max_iter, dbgInfo)
%% 🌟 BTR Solver via Dual Low-Rank ADMM Optimization 🌟
fprintf('\n');
fprintf('╔════════════════════════════════════════════════════════════════════╗\n');
fprintf('║     🚀 Solving Bidirectional Tensor Representation (BTR) Model     ║\n');
fprintf('║     🔄 ADMM-based optimization with transform-domain constraints    ║\n');
fprintf('╚════════════════════════════════════════════════════════════════════╝\n\n');

%% Dimensions and Initialization
[n1, n2, n3] = size(X);              % Input tensor dimensions
[~, n4, ~] = size(D);                % Row dictionary D
[~, n5, ~] = size(Dt);               % Column dictionary Dt

% Initialize primal variables
W = zeros(n4, n2, n3);               % Row coefficients
R = zeros(n5, n2, n1);               % Column coefficients
M = W; N = R; E = zeros(n1, n2, n3); % Auxiliary variables
F = permute(E, [3, 2, 1]);           % Permuted version of E

% Initialize dual variables
Y1 = M; Y2 = N; Y3 = E; Y4 = F;

%% ADMM Parameters
beta1 = 1e-4; beta2 = 1e-4;
max_beta = 1e8; tol = 1e-6; rho = 1.1; iter = 0;

%% Precompute transform-domain dictionary inverses and transposes
Y = permute(X, [3, 2, 1]);           % Permuted input tensor for column direction
D_inv  = t_inverse(D,  transformRow);
D_T    = tran(D,        transformRow);
Dt_inv = t_inverse(Dt,  transformCol);
Dt_T   = tran(Dt,       transformCol);

%% Main Optimization Loop
while iter < max_iter
    iter = iter + 1;

    % ----- Update W -----
    Q1 = M + Y1 / beta1;
    Q2 = X - E + Y3 / beta1;
    W_prev = W;
    W = tprod(D_inv, Q1 + tprod(D_T, Q2, transformRow), transformRow);

    % ----- Update R -----
    Q3 = N + Y2 / beta2;
    Q4 = Y - F + Y4 / beta2;
    R_prev = R;
    R = tprod(Dt_inv, Q3 + tprod(Dt_T, Q4, transformCol), transformCol);

    % ----- Update M (proximal TNN) -----
    M_prev = M;
    M = prox_tnn(W - Y1 / beta1, alpha / beta1, transformRow);

    % ----- Update N (proximal TNN) -----
    N_prev = N;
    N = prox_tnn(R - Y2 / beta2, (1 - alpha) / beta2, transformCol);

    % ----- Update E (proximal L1) -----
    E_prev = E;
    R3 = X - tprod(D, W, transformRow) + Y3 / beta1;
    F3 = Y - tprod(Dt, R, transformCol) + Y4 / beta2;
    E = prox_l1((beta1 * R3 + beta2 * permute(F3, [3, 2, 1])) / (beta1 + beta2), ...
                lambda / (beta1 + beta2));
    F = permute(E, [3, 2, 1]);

    % ----- Compute primal and dual gaps -----
    leq1 = M - W;
    leq2 = N - R;
    leq3 = X - tprod(D, W, transformRow) - E;
    leq4 = Y - tprod(Dt, R, transformCol) - F;

    % Max violation and variable updates
    opt_gap = max([ ...
        max(abs(leq1(:))), max(abs(leq2(:))), ...
        max(abs(leq3(:))), max(abs(leq4(:))), ...
        max(abs(M(:) - M_prev(:))), ...
        max(abs(N(:) - N_prev(:))), ...
        max(abs(W(:) - W_prev(:))), ...
        max(abs(R(:) - R_prev(:))), ...
        max(abs(E(:) - E_prev(:))) ...
    ]);

    % Optional debug info
    if iter == 1 || mod(iter, 50) == 0
        fprintf('⚙  BTR Iter %3d: opt-gap = %.2e\n', iter, opt_gap);
    end

    % ----- Check convergence -----
    if opt_gap < tol
        fprintf('✅ Converged at iteration %d with opt-gap = %.2e\n', iter, opt_gap);
        break;
    end

    % ----- Update dual variables -----
    Y1 = Y1 + beta1 * leq1;
    Y2 = Y2 + beta2 * leq2;
    Y3 = Y3 + beta1 * leq3;
    Y4 = Y4 + beta2 * leq4;

    % ----- Update penalty parameters -----
    beta1 = min(beta1 * rho, max_beta);
    beta2 = min(beta2 * rho, max_beta);
end
end
