import type { AppState, StateRepository } from '@domain/ports/StateRepository';
import { DEFAULT_TARGETS } from '@domain/value-objects/GaugeType';

interface ElectronAPI {
  saveData: (json: string) => void;
  loadData: () => Promise<string | null>;
}

function getElectronAPI(): ElectronAPI | null {
  if (typeof window !== 'undefined' && (window as any).electronAPI) {
    return (window as any).electronAPI;
  }
  return null;
}

export class LocalStorageRepository implements StateRepository {
  private readonly storageKey = 'dd3v3';

  async load(): Promise<AppState | null> {
    try {
      let raw: string | null = null;
      const api = getElectronAPI();
      if (api) raw = await api.loadData();
      if (!raw && typeof localStorage !== 'undefined') {
        raw = localStorage.getItem(this.storageKey) || localStorage.getItem('dd3v2');
      }
      if (!raw) return null;
      return this.deserialize(raw);
    } catch {
      return null;
    }
  }

  save(state: AppState): void {
    try {
      const d = JSON.parse(JSON.stringify(state));
      // Reset runtime state before persisting
      d.enclos.forEach((e: any) => {
        e.timer.running = false;
        e.alerted = {};
      });
      const json = JSON.stringify(d);
      const api = getElectronAPI();
      if (api) api.saveData(json);
      if (typeof localStorage !== 'undefined') {
        localStorage.setItem(this.storageKey, json);
      }
    } catch (e) {
      console.error('Erreur sauvegarde:', (e as Error).message);
    }
  }

  private deserialize(raw: string): AppState {
    const d = JSON.parse(raw);
    const state: AppState = {
      enclos: d.enclos || [],
      activeId: d.activeId ?? null,
      nextEnclosId: d.nextEnclosId || 1,
      alarmSound: d.alarmSound || 'arpege',
      notifsEnabled: d.notifsEnabled !== undefined ? d.notifsEnabled : true,
      ntfyTopic: d.ntfyTopic || '',
      archivedStats: d.archivedStats || [],
      inventaire: d.inventaire || {},
      workflows: d.workflows || [],
      accouplements: d.accouplements || [],
    };

    // Migration: old ntfyUrl format → ntfyTopic
    if (!state.ntfyTopic && d.ntfyUrl) {
      const m = d.ntfyUrl.match(/\/([^\/]+)$/);
      if (m) state.ntfyTopic = m[1];
    }

    // Migrate enclos data
    state.enclos.forEach((enc: any) => {
      enc.timer = enc.timer || { running: false, startTime: null, pausedAt: null, pausedMs: 0, snapGauges: {}, snapStats: {} };
      enc.timer.running = false;
      enc.alerted = {};
      if (enc.gaugeLevels.mangeoire === undefined) enc.gaugeLevels.mangeoire = 0;
      enc.dragodindes.forEach((dd: any) => {
        if (dd.stats.xp === undefined) dd.stats.xp = 1;
        // Migration: old serenite target → gauge-based targets
        if (dd.targets.serenite !== undefined && dd.targets.baffeur === undefined) {
          const old = { ...dd.targets };
          dd.targets = {
            baffeur: old.serenite ?? -5000,
            caresseur: Math.max(0, old.serenite ?? 40),
            foudroyeur: old.endurance ?? 20000,
            abreuvoir: old.maturite ?? 20000,
            dragofesse: old.amour ?? 20000,
            mangeoire: 100,
          };
        }
        Object.keys(DEFAULT_TARGETS).forEach(k => {
          if (dd.targets[k] === undefined) dd.targets[k] = (DEFAULT_TARGETS as any)[k];
        });
      });
    });

    if (!state.activeId && state.enclos.length) {
      state.activeId = state.enclos[0].id;
    }

    return state;
  }
}
