import AsyncStorage from '@react-native-async-storage/async-storage';
import { Plant, Language, AppearanceMode, ColorPalette } from '../types';

const STORAGE_KEY = 'greenlens_plants';
const LANG_KEY = 'greenlens_language';
const ONBOARDING_KEY = 'greenlens_onboarding_complete';
const APPEARANCE_MODE_KEY = 'greenlens_appearance_mode';
const COLOR_PALETTE_KEY = 'greenlens_color_palette';
const PROFILE_IMAGE_KEY = 'greenlens_profile_image';
const PROFILE_NAME_KEY = 'greenlens_profile_name';
const LEXICON_SEARCH_HISTORY_KEY = 'greenlens_lexicon_search_history';
const LEXICON_SEARCH_HISTORY_LIMIT = 10;
const DEFAULT_PROFILE_NAME = 'GreenLens User';

const isAppearanceMode = (value: string | null): value is AppearanceMode =>
  value === 'system' || value === 'light' || value === 'dark';

const isColorPalette = (value: string | null): value is ColorPalette =>
  value === 'forest' || value === 'ocean' || value === 'sunset' || value === 'mono';

const normalizeSearchQuery = (value: string): string => {
  return value
    .toLowerCase()
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .trim()
    .replace(/\s+/g, ' ');
};

export const StorageService = {
  getPlants: async (): Promise<Plant[]> => {
    try {
      const json = await AsyncStorage.getItem(STORAGE_KEY);
      return json ? JSON.parse(json) : [];
    } catch (e) {
      console.error('Failed to load plants', e);
      return [];
    }
  },

  savePlant: async (plant: Plant): Promise<void> => {
    const plants = await StorageService.getPlants();
    const updatedPlants = [plant, ...plants];
    await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(updatedPlants));
  },

  deletePlant: async (id: string): Promise<void> => {
    const plants = await StorageService.getPlants();
    const updatedPlants = plants.filter(p => p.id !== id);
    await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(updatedPlants));
  },

  updatePlant: async (updatedPlant: Plant): Promise<void> => {
    const plants = await StorageService.getPlants();
    const index = plants.findIndex(p => p.id === updatedPlant.id);
    if (index !== -1) {
      plants[index] = updatedPlant;
      await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(plants));
    }
  },

  getLanguage: async (): Promise<Language> => {
    try {
      const lang = await AsyncStorage.getItem(LANG_KEY);
      return (lang as Language) || 'en';
    } catch (e) {
      return 'en';
    }
  },

  saveLanguage: async (lang: Language): Promise<void> => {
    await AsyncStorage.setItem(LANG_KEY, lang);
  },

  getAppearanceMode: async (): Promise<AppearanceMode> => {
    try {
      const mode = await AsyncStorage.getItem(APPEARANCE_MODE_KEY);
      return isAppearanceMode(mode) ? mode : 'system';
    } catch (e) {
      return 'system';
    }
  },

  saveAppearanceMode: async (mode: AppearanceMode): Promise<void> => {
    await AsyncStorage.setItem(APPEARANCE_MODE_KEY, mode);
  },

  getColorPalette: async (): Promise<ColorPalette> => {
    try {
      const palette = await AsyncStorage.getItem(COLOR_PALETTE_KEY);
      return isColorPalette(palette) ? palette : 'forest';
    } catch (e) {
      return 'forest';
    }
  },

  saveColorPalette: async (palette: ColorPalette): Promise<void> => {
    await AsyncStorage.setItem(COLOR_PALETTE_KEY, palette);
  },

  getProfileImage: async (): Promise<string | null> => {
    try {
      const imageUri = await AsyncStorage.getItem(PROFILE_IMAGE_KEY);
      return imageUri || null;
    } catch (e) {
      return null;
    }
  },

  saveProfileImage: async (imageUri: string | null): Promise<void> => {
    if (!imageUri) {
      await AsyncStorage.removeItem(PROFILE_IMAGE_KEY);
      return;
    }
    await AsyncStorage.setItem(PROFILE_IMAGE_KEY, imageUri);
  },

  getProfileName: async (): Promise<string> => {
    try {
      const profileName = await AsyncStorage.getItem(PROFILE_NAME_KEY);
      const normalized = profileName?.trim();
      return normalized || DEFAULT_PROFILE_NAME;
    } catch (e) {
      return DEFAULT_PROFILE_NAME;
    }
  },

  saveProfileName: async (name: string): Promise<void> => {
    const normalized = name.trim();
    await AsyncStorage.setItem(PROFILE_NAME_KEY, normalized || DEFAULT_PROFILE_NAME);
  },

  getOnboardingComplete: async (): Promise<boolean> => {
    try {
      const value = await AsyncStorage.getItem(ONBOARDING_KEY);
      return value === 'true';
    } catch (e) {
      return false;
    }
  },

  setOnboardingComplete: async (complete: boolean): Promise<void> => {
    await AsyncStorage.setItem(ONBOARDING_KEY, complete ? 'true' : 'false');
  },

  getLexiconSearchHistory: async (): Promise<string[]> => {
    try {
      const value = await AsyncStorage.getItem(LEXICON_SEARCH_HISTORY_KEY);
      if (!value) return [];

      const parsed = JSON.parse(value);
      if (!Array.isArray(parsed)) return [];

      return parsed.filter((item): item is string => typeof item === 'string');
    } catch (e) {
      console.error('Failed to load lexicon search history', e);
      return [];
    }
  },

  saveLexiconSearchQuery: async (query: string): Promise<void> => {
    const trimmed = query.trim();
    if (!trimmed) return;

    const history = await StorageService.getLexiconSearchHistory();
    const normalized = normalizeSearchQuery(trimmed);

    const deduped = history.filter(
      item => normalizeSearchQuery(item) !== normalized
    );

    const updated = [trimmed, ...deduped].slice(0, LEXICON_SEARCH_HISTORY_LIMIT);
    await AsyncStorage.setItem(LEXICON_SEARCH_HISTORY_KEY, JSON.stringify(updated));
  },

  clearLexiconSearchHistory: async (): Promise<void> => {
    await AsyncStorage.removeItem(LEXICON_SEARCH_HISTORY_KEY);
  },
};
