// lib/core/policies/policy-manager.ts
import mobile from './defaults.mobile.json';
import tablet from './defaults.tablet.json';
import desktop from './defaults.desktop.json';
import { detectDeviceKind, prefersReducedMotion, isLowEndHardware } from './detectors';
import type { Policy, DeviceKind } from './types';

const STORAGE_DEVICE_KEY = 'DEVICE_KIND';
const STORAGE_POLICY_KEY = 'OS_LAST_POLICY';

function deepMerge<T>(base: T, patch?: Partial<T>): T {
  if (!patch) return base;
  const out: any = Array.isArray(base) ? [...(base as any)] : { ...(base as any) };
  for (const k of Object.keys(patch)) {
    const v = (patch as any)[k];
    if (v && typeof v === 'object' && !Array.isArray(v))
      out[k] = deepMerge((out as any)[k] ?? {}, v);
    else out[k] = v;
  }
  return out;
}

export class PolicyManager {
  private cached: Policy | null = null;
  private overrides: Partial<Policy> | null = null;

  /** محاولة قراءة آخر سياسة محفوظة (للاختبارات/الإقلاع السريع) */
  private readLastPolicy(): Policy | null {
    try {
      const raw = sessionStorage.getItem(STORAGE_POLICY_KEY);
      return raw ? (JSON.parse(raw) as Policy) : null;
    } catch {
      return null;
    }
  }

  private writeLastPolicy(p: Policy) {
    try {
      sessionStorage.setItem(STORAGE_POLICY_KEY, JSON.stringify(p));
    } catch {}
  }

  compute(device?: DeviceKind): Policy {
    // === Context Cache: احترم الجهاز المخزون إن لم يُمرَّر يدويًا
    let kind: DeviceKind | undefined = device;
    if (!kind) {
      try {
        const cachedKind = sessionStorage.getItem(STORAGE_DEVICE_KEY) as DeviceKind | null;
        kind = cachedKind ?? detectDeviceKind();
      } catch {
        kind = detectDeviceKind();
      }
    }

    // اكتب نوع الجهاز المختار للذاكرة القصيرة
    try {
      sessionStorage.setItem(STORAGE_DEVICE_KEY, kind!);
    } catch {}

    const base: Policy =
      kind === 'mobile'
        ? (mobile as Policy)
        : kind === 'tablet'
        ? (tablet as Policy)
        : (desktop as Policy);

    const reduceMotion = prefersReducedMotion();
    const lowEnd = isLowEndHardware();

    // === Policy confidence heuristic
    const confidence = kind === 'desktop' ? 1 : kind === 'tablet' ? 0.9 : 0.8;

    let adjusted: Policy = deepMerge(base, {
      ui: { animations: reduceMotion ? 'reduced' : base.ui.animations },
      behavior: { perfMode: base.behavior.perfMode || lowEnd },
      meta: { confidence },
    } as unknown as Partial<Policy>);

    if (this.overrides) adjusted = deepMerge(adjusted, this.overrides);

    this.cached = adjusted;
    this.writeLastPolicy(adjusted);
    return adjusted;
  }

  setOverrides(o: Partial<Policy>) {
    this.overrides = deepMerge(this.overrides ?? {}, o);
    this.cached = null;
  }

  clearOverrides() {
    this.overrides = null;
    this.cached = null;
  }

  getCached(): Policy | null {
    if (this.cached) return this.cached;
    return this.readLastPolicy();
  }
}

export const policyManager = new PolicyManager();
