import { create } from "zustand";

const CLAIMED_STORAGE_KEY  = "mindavio-claimed-rewards";
const DISMISSED_STORAGE_KEY = "mindavio-dismissed-smart-notifs";
const PREFERENCES_STORAGE_KEY = "mindavio-notification-preferences";

/* ── Smart notification types ─────────────────────────────────────────────── */

export type SmartNotificationType =
  | "task_overdue"
  | "task_deadline_today"
  | "task_deadline_tomorrow"
  | "event_upcoming"
  | "journal_reminder"
  | "habit_due"
  | "goal_due"
  | "reminder_due"
  | "achievement_completed"
  | "reward_claimable";

export type SmartNotificationLevel =
  | "urgent"
  | "warning"
  | "info"
  | "achievement"
  | "reward";

export interface SmartNotification {
  id:        string;
  type:      SmartNotificationType;
  title:     string;
  body:      string;
  level:     SmartNotificationLevel;
  link?:     string;
  createdAt: number;
}

export type NotificationCategory =
  | "tasks"
  | "calendar"
  | "journal"
  | "habits"
  | "goals"
  | "reminders"
  | "achievements"
  | "messages"
  | "projects";

export type NotificationPreferences = Record<NotificationCategory, boolean>;

export const DEFAULT_NOTIFICATION_PREFERENCES: NotificationPreferences = {
  tasks: true,
  calendar: true,
  journal: true,
  habits: true,
  goals: true,
  reminders: true,
  achievements: true,
  messages: true,
  projects: true,
};

export function getSmartNotificationCategory(
  type: SmartNotificationType,
): NotificationCategory {
  if (type.startsWith("task_")) return "tasks";
  if (type === "event_upcoming") return "calendar";
  if (type === "journal_reminder") return "journal";
  if (type === "habit_due") return "habits";
  if (type === "goal_due") return "goals";
  if (type === "reminder_due") return "reminders";
  return "achievements";
}

/* ── Store ────────────────────────────────────────────────────────────────── */

interface NotificationStore {
  smartNotifications: SmartNotification[];
  dismissedIds:       string[];
  lastCheckedAt:      number | null;
  notificationPreferences: NotificationPreferences;

  /* Claimed rewards (keyed by achievementId → ISO date string) */
  claimedRewards:     Record<string, string>;

  addSmartNotification:    (notif: SmartNotification) => void;
  dismissSmartNotification:(id: string) => void;
  clearAllSmart:           () => void;
  setLastChecked:          (ts: number) => void;
  setNotificationPreference: (category: NotificationCategory, enabled: boolean) => void;
  toggleNotificationPreference: (category: NotificationCategory) => void;
  isNotificationCategoryEnabled: (category: NotificationCategory) => boolean;

  claimReward:     (achievementId: string) => void;
  isRewardClaimed: (achievementId: string) => boolean;
}

/* ── Persistence helpers ─────────────────────────────────────────────────── */

function loadClaimed(): Record<string, string> {
  if (typeof window === "undefined") return {};
  try { return JSON.parse(localStorage.getItem(CLAIMED_STORAGE_KEY) || "{}"); }
  catch { return {}; }
}

function saveClaimed(r: Record<string, string>) {
  try { localStorage.setItem(CLAIMED_STORAGE_KEY, JSON.stringify(r)); } catch { /* ignore */ }
}

function loadDismissed(): string[] {
  if (typeof window === "undefined") return [];
  try { return JSON.parse(localStorage.getItem(DISMISSED_STORAGE_KEY) || "[]"); }
  catch { return []; }
}

function saveDismissed(ids: string[]) {
  // Keep only last 200 dismissed IDs to avoid unbounded growth
  const trimmed = ids.slice(-200);
  try { localStorage.setItem(DISMISSED_STORAGE_KEY, JSON.stringify(trimmed)); } catch { /* ignore */ }
}

function loadPreferences(): NotificationPreferences {
  if (typeof window === "undefined") return DEFAULT_NOTIFICATION_PREFERENCES;
  try {
    const stored = JSON.parse(localStorage.getItem(PREFERENCES_STORAGE_KEY) || "{}");
    return { ...DEFAULT_NOTIFICATION_PREFERENCES, ...stored };
  } catch {
    return DEFAULT_NOTIFICATION_PREFERENCES;
  }
}

function savePreferences(preferences: NotificationPreferences) {
  try {
    localStorage.setItem(PREFERENCES_STORAGE_KEY, JSON.stringify(preferences));
  } catch { /* ignore */ }
}

/* ── Store instance ──────────────────────────────────────────────────────── */

export const useNotificationStore = create<NotificationStore>((set, get) => ({
  smartNotifications: [],
  dismissedIds:       loadDismissed(),
  lastCheckedAt:      null,
  notificationPreferences: loadPreferences(),
  claimedRewards:     loadClaimed(),

  addSmartNotification: (notif) => set((s) => {
    const category = getSmartNotificationCategory(notif.type);
    if (!s.notificationPreferences[category]) return s;
    // Skip if already exists or has been dismissed
    if (s.smartNotifications.some((n) => n.id === notif.id)) return s;
    if (s.dismissedIds.includes(notif.id)) return s;
    return { smartNotifications: [notif, ...s.smartNotifications].slice(0, 30) };
  }),

  dismissSmartNotification: (id) => set((s) => {
    const dismissedIds = [...s.dismissedIds, id];
    saveDismissed(dismissedIds);
    return {
      smartNotifications: s.smartNotifications.filter((n) => n.id !== id),
      dismissedIds,
    };
  }),

  clearAllSmart: () => set((s) => {
    const ids = s.smartNotifications.map((n) => n.id);
    const dismissedIds = [...s.dismissedIds, ...ids];
    saveDismissed(dismissedIds);
    return { smartNotifications: [], dismissedIds };
  }),

  setLastChecked: (ts) => set({ lastCheckedAt: ts }),

  setNotificationPreference: (category, enabled) => set((s) => {
    const notificationPreferences = {
      ...s.notificationPreferences,
      [category]: enabled,
    };
    savePreferences(notificationPreferences);

    return {
      notificationPreferences,
      smartNotifications: enabled
        ? s.smartNotifications
        : s.smartNotifications.filter(
            (notification) => getSmartNotificationCategory(notification.type) !== category,
          ),
    };
  }),

  toggleNotificationPreference: (category) => {
    const current = get().notificationPreferences[category];
    get().setNotificationPreference(category, !current);
  },

  isNotificationCategoryEnabled: (category) => {
    return get().notificationPreferences[category] ?? true;
  },

  claimReward: (achievementId) => set((s) => {
    const claimedRewards = { ...s.claimedRewards, [achievementId]: new Date().toISOString() };
    saveClaimed(claimedRewards);
    return { claimedRewards };
  }),

  isRewardClaimed: (achievementId) => {
    return !!get().claimedRewards[achievementId];
  },
}));
