```python
"""
UTFANSWF v22 — Covariance-Aware BAO Bridge
-----------------------------------------

Purpose:
Implements proper covariance-preserving BAO (D_M, H) handling
for Row 20 cosmology gate without altering physics, datasets,
or thresholds.

This replaces flattened BAO handling with paired vector treatment
and correct covariance propagation.

Status:
v22 structural fix — no parameter changes
"""

import numpy as np
import pandas as pd


# ============================================================
# DATA LOADERS
# ============================================================

def load_bao_dm_h_data(data_path, theory_path, cov_path):
    data = pd.read_csv(data_path)
    theory = pd.read_csv(theory_path)
    cov = pd.read_csv(cov_path, header=None).values

    return data, theory, cov


# ============================================================
# BLOCK CONSTRUCTION
# ============================================================

def build_bao_blocks(data, theory, cov):
    """
    Constructs paired vectors and covariance blocks for each redshift.
    Assumes ordering:
    [DM_1, H_1, DM_2, H_2, ...]
    """

    n = len(data)
    blocks = []

    for i in range(n):
        DM = data.iloc[i]["DM"]
        H = data.iloc[i]["H"]

        DM_th = theory.iloc[i]["DM"]
        H_th = theory.iloc[i]["H"]

        d_vec = np.array([DM, H])
        t_vec = np.array([DM_th, H_th])

        idx = 2 * i
        C_i = cov[idx:idx+2, idx:idx+2]

        blocks.append((d_vec, t_vec, C_i))

    return blocks


# ============================================================
# CORE CHI² COMPUTATION
# ============================================================

def compute_bao_chi2(blocks):
    chi2 = 0.0

    for d_vec, t_vec, C_i in blocks:
        delta = d_vec - t_vec

        try:
            C_inv = np.linalg.inv(C_i)
        except np.linalg.LinAlgError:
            # numerical guard
            C_inv = np.linalg.pinv(C_i)

        chi2_i = delta.T @ C_inv @ delta
        chi2 += chi2_i

    return chi2


# ============================================================
# OPTIONAL: COVARIANCE PROPAGATION (for bridge layer)
# ============================================================

def propagate_covariance(C, Pi):
    """
    Applies covariance transformation:
    C' = Pi C Pi^T
    """
    return Pi @ C @ Pi.T


# ============================================================
# MAIN ENTRY FOR ROW 20
# ============================================================

def run_bao_dm_h_covariance_bridge(
    data_path,
    theory_path,
    cov_path,
    return_details=False
):
    data, theory, cov = load_bao_dm_h_data(
        data_path,
        theory_path,
        cov_path
    )

    blocks = build_bao_blocks(data, theory, cov)
    chi2 = compute_bao_chi2(blocks)

    result = {
        "chi2": float(chi2),
        "n_points": len(blocks) * 2,
        "n_pairs": len(blocks),
        "status": "covariance_aware_bao_dm_h"
    }

    if return_details:
        result["blocks"] = blocks

    return result


# ============================================================
# DEBUG / STANDALONE RUN
# ============================================================

if __name__ == "__main__":
    DATA = "datasets/bao_data_DM_H.csv"
    THEORY = "datasets/bao_theory_DM_H.csv"
    COV = "datasets/bao_cov_DM_H.csv"

    res = run_bao_dm_h_covariance_bridge(DATA, THEORY, COV)

    print("\n=== BAO DM/H Covariance Bridge Result ===")
    for k, v in res.items():
        if k != "blocks":
            print(f"{k}: {v}")
```
