import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { apiFetch } from '@/lib/tauri'

// =====================
// Types
// =====================

export interface ThemeVariables {
  colors: Record<string, string>
  text: Record<string, string>
  accent: Record<string, string>
  semantic: Record<string, string>
  spacing: Record<string, string>
  typography: Record<string, string>
  effects: Record<string, string>
}

export interface ThemeMetadata {
  author?: string
  version?: string
  tags?: string[]
  base?: string | null
  exported_at?: string | null
}

export interface Theme {
  id: string
  name: string
  description?: string
  is_default: boolean
  is_system: boolean
  variables: ThemeVariables
  metadata?: ThemeMetadata
  created_at?: string
  updated_at?: string
}

export interface DesignTokens {
  version: string
  description: string
  usage: string
  tokens: ThemeVariables
  guidelines: Record<string, string>
  examples: Record<string, string>
}

// Uses relative URLs - works with Vite proxy in dev and Traefik in production
const API_URL = ''

// =====================
// Store
// =====================

export const useThemeStore = defineStore('theme', () => {
  // State
  const themes = ref<Theme[]>([])
  const activeTheme = ref<Theme | null>(null)
  const previewTheme = ref<ThemeVariables | null>(null)
  const designTokens = ref<DesignTokens | null>(null)
  const loading = ref(false)
  const saving = ref(false)
  const error = ref<string | null>(null)

  // Getters
  const currentVariables = computed(() => {
    if (previewTheme.value) return previewTheme.value
    return activeTheme.value?.variables || null
  })

  const systemThemes = computed(() =>
    themes.value.filter(t => t.is_system)
  )

  const userThemes = computed(() =>
    themes.value.filter(t => !t.is_system)
  )

  const hasUnsavedChanges = computed(() => previewTheme.value !== null)

  const flattenedVariables = computed(() => {
    const vars = currentVariables.value
    if (!vars) return {}

    const flat: Record<string, string> = {}
    for (const category of Object.keys(vars)) {
      for (const [key, value] of Object.entries(vars[category as keyof ThemeVariables])) {
        flat[`--${key}`] = value
      }
    }
    return flat
  })

  // Actions
  async function fetchThemes() {
    loading.value = true
    error.value = null
    try {
      const res = await apiFetch(`${API_URL}/api/themes`)
      themes.value = await res.json()

      const defaultTheme = themes.value.find(t => t.is_default)
      if (defaultTheme) {
        activeTheme.value = defaultTheme
        applyTheme(defaultTheme.variables)
      }
    } catch (e) {
      error.value = 'Error loading themes'
      console.error(e)
    } finally {
      loading.value = false
    }
  }

  async function fetchDesignTokens() {
    try {
      const res = await apiFetch(`${API_URL}/api/design-tokens`)
      designTokens.value = await res.json()
    } catch (e) {
      console.error('Error fetching design tokens:', e)
    }
  }

  async function saveTheme(theme: Partial<Theme> & { name: string; variables: ThemeVariables }) {
    saving.value = true
    try {
      const res = await apiFetch(`${API_URL}/api/themes`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(theme)
      })
      const result = await res.json()
      await fetchThemes()
      return result
    } catch (e) {
      error.value = 'Error saving theme'
      throw e
    } finally {
      saving.value = false
    }
  }

  async function updateTheme(id: string, data: { name?: string; description?: string; variables?: ThemeVariables; metadata?: ThemeMetadata }) {
    saving.value = true
    try {
      const res = await apiFetch(`${API_URL}/api/themes/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      })
      const result = await res.json()
      if (result.error) {
        error.value = result.error
        return null
      }
      await fetchThemes()
      return result
    } catch (e) {
      error.value = 'Error updating theme'
      throw e
    } finally {
      saving.value = false
    }
  }

  async function deleteTheme(id: string) {
    try {
      const res = await apiFetch(`${API_URL}/api/themes/${id}`, { method: 'DELETE' })
      const result = await res.json()
      if (result.error) {
        error.value = result.error
        return false
      }
      await fetchThemes()
      return true
    } catch (e) {
      error.value = 'Error deleting theme'
      return false
    }
  }

  async function setDefaultTheme(id: string) {
    try {
      await apiFetch(`${API_URL}/api/themes/${id}/default`, { method: 'POST' })
      await fetchThemes()
    } catch (e) {
      error.value = 'Error setting default theme'
    }
  }

  async function cloneTheme(id: string, newName: string) {
    const original = themes.value.find(t => t.id === id)
    if (!original) return null

    return saveTheme({
      name: newName,
      description: `Cloned from ${original.name}`,
      variables: JSON.parse(JSON.stringify(original.variables)),
      metadata: { base: id }
    })
  }

  function applyTheme(variables: ThemeVariables) {
    const root = document.documentElement

    for (const category of Object.keys(variables)) {
      for (const [key, value] of Object.entries(variables[category as keyof ThemeVariables])) {
        root.style.setProperty(`--${key}`, value)
      }
    }
  }

  function selectTheme(theme: Theme) {
    activeTheme.value = theme
    previewTheme.value = null
    applyTheme(theme.variables)
  }

  function setPreview(variables: ThemeVariables | null) {
    previewTheme.value = variables
    if (variables) {
      applyTheme(variables)
    } else if (activeTheme.value) {
      applyTheme(activeTheme.value.variables)
    }
  }

  function updateVariable(category: keyof ThemeVariables, key: string, value: string) {
    if (!previewTheme.value && activeTheme.value) {
      previewTheme.value = JSON.parse(JSON.stringify(activeTheme.value.variables))
    }

    if (previewTheme.value && previewTheme.value[category]) {
      previewTheme.value[category][key] = value
      document.documentElement.style.setProperty(`--${key}`, value)
    }
  }

  function exportTheme(theme: Theme): string {
    return JSON.stringify({
      name: theme.name,
      description: theme.description,
      variables: theme.variables,
      metadata: {
        ...theme.metadata,
        exported_at: new Date().toISOString()
      }
    }, null, 2)
  }

  async function importTheme(jsonString: string) {
    try {
      const data = JSON.parse(jsonString)
      if (!data.name || !data.variables) {
        throw new Error('Invalid theme format')
      }
      return saveTheme({
        name: data.name,
        description: data.description,
        variables: data.variables,
        metadata: data.metadata
      })
    } catch (e) {
      error.value = 'Invalid theme file'
      throw e
    }
  }

  function resetPreview() {
    previewTheme.value = null
    if (activeTheme.value) {
      applyTheme(activeTheme.value.variables)
    }
  }

  async function commitPreview(name?: string) {
    if (!previewTheme.value) return

    const themeName = name || activeTheme.value?.name || 'Custom Theme'
    const themeId = activeTheme.value?.is_system ? undefined : activeTheme.value?.id

    await saveTheme({
      id: themeId,
      name: themeName,
      variables: previewTheme.value
    })
    previewTheme.value = null
  }

  return {
    // State
    themes,
    activeTheme,
    previewTheme,
    designTokens,
    loading,
    saving,
    error,
    // Getters
    currentVariables,
    systemThemes,
    userThemes,
    hasUnsavedChanges,
    flattenedVariables,
    // Actions
    fetchThemes,
    fetchDesignTokens,
    saveTheme,
    updateTheme,
    deleteTheme,
    setDefaultTheme,
    cloneTheme,
    applyTheme,
    selectTheme,
    setPreview,
    updateVariable,
    exportTheme,
    importTheme,
    resetPreview,
    commitPreview
  }
})
