import json, os, hashlib, datetime
import numpy as np
import pandas as pd

def sha256_file(path: str) -> str:
    h = hashlib.sha256()
    with open(path, "rb") as f:
        for chunk in iter(lambda: f.read(1<<20), b""):
            h.update(chunk)
    return h.hexdigest()

def load_vector_csv(path: str) -> np.ndarray:
    df = pd.read_csv(path, header=None, comment='#')
    # Accept either a single column or multiple columns
    if df.shape[1] == 1:
        return df.iloc[:,0].to_numpy(dtype=float)
    return df.to_numpy(dtype=float).reshape(-1)

def load_matrix_csv(path: str) -> np.ndarray:
    df = pd.read_csv(path, header=None, comment='#')
    return df.to_numpy(dtype=float)

def cov_diagnostics(C: np.ndarray) -> dict:
    Csym = 0.5*(C + C.T)
    eig = np.linalg.eigvalsh(Csym)
    return {
        "n": int(C.shape[0]),
        "symmetry_Linf": float(np.max(np.abs(C - C.T))),
        "min_eig": float(np.min(eig)),
        "max_eig": float(np.max(eig)),
        "cond_2": float(np.linalg.cond(Csym)),
    }

def chi2(d: np.ndarray, t: np.ndarray, C: np.ndarray) -> float:
    r = (d - t).reshape(-1,1)
    Csym = 0.5*(C + C.T)
    # Use pinv for stability; report cond separately
    Ci = np.linalg.pinv(Csym)
    return float((r.T @ Ci @ r)[0,0])

def write_outputs(out_dir: str, result: dict):
    os.makedirs(out_dir, exist_ok=True)
    with open(os.path.join(out_dir, "result.json"), "w", encoding="utf-8") as f:
        json.dump(result, f, indent=2, sort_keys=True)
