import os
import cv2
import numpy as np
from tqdm import tqdm
from .interface import BaseAdapter

class AuditEngine:
    def __init__(self, adapter: BaseAdapter, output_dir="data/audit_payload"):
        self.adapter = adapter
        self.output_dir = output_dir
        self.dims = ['Lux+', 'Lux-', 'DPI', 'MBlur', 'Defocus', 'ISO']

    def apply_stress(self, image_path: str):
        if not os.path.exists(image_path): 
            raise FileNotFoundError(f"找不到图片: {image_path}")
        img = cv2.imread(image_path)
        h, w = img.shape[:2]
        for d in self.dims: 
            os.makedirs(os.path.join(self.output_dir, d), exist_ok=True)
        
        for i in tqdm(range(1, 101), desc="注入物理应力"):
            cv2.imwrite(os.path.join(self.output_dir, "Lux+", f"Lux+_{i:03d}.jpg"), np.clip(img.astype('float32') + (i * 2.55), 0, 255).astype('uint8'))
            cv2.imwrite(os.path.join(self.output_dir, "Lux-", f"Lux-_{i:03d}.jpg"), np.clip(img.astype('float32') - (i * 2.55), 0, 255).astype('uint8'))
            cv2.imwrite(os.path.join(self.output_dir, "ISO", f"ISO_{i:03d}.jpg"), np.clip(img.astype('float32') + np.random.normal(0, i * 5.0, img.shape), 0, 255).astype('uint8'))
            k = i * 2 + 1; kernel = np.zeros((k, k)); kernel[k//2, :] = 1; kernel /= kernel.sum()
            cv2.imwrite(os.path.join(self.output_dir, "MBlur", f"MBlur_{i:03d}.jpg"), cv2.filter2D(img, -1, kernel))
            sigma = i * 0.5; ksize = int(sigma * 6) // 2 * 2 + 1
            cv2.imwrite(os.path.join(self.output_dir, "Defocus", f"Defocus_{i:03d}.jpg"), cv2.GaussianBlur(img, (ksize, ksize), sigmaX=sigma))
            s = max(0.01, (101 - i) / 100)
            tmp = cv2.resize(img, (int(w*s), int(h*s)), interpolation=cv2.INTER_AREA)
            cv2.imwrite(os.path.join(self.output_dir, "DPI", f"DPI_{i:03d}.jpg"), cv2.resize(tmp, (w, h), interpolation=cv2.INTER_NEAREST))

    def run_audit(self):
        results = []
        for d in self.dims:
            path = os.path.join(self.output_dir, d)
            files = sorted(os.listdir(path))
            for f in files:
                metric = self.adapter.run_inference(os.path.join(path, f))
                results.append({
                    "dimension": d, 
                    "level": int(f.split('_')[-1].split('.')[0]), 
                    "metric": metric
                })
        return results