import { defineStore } from 'pinia'
import { useRequestFetch } from '#imports'

export interface TableMetadata {
  table: string
  rowCount: number
  primaryKey: string
  approxSizeBytes: number
  columns: string[]
  createdAtRange?: {
    from: string
    to: string
  }
  lastRefreshed?: string
  sampleRow?: Record<string, unknown>
}

export interface MetadataState {
  metadata: TableMetadata[]
  loading: boolean
  error: string | null
  lastUpdated: string | null
  initialized: boolean
}

export const useMetadataStore = defineStore('metadata', {
  state: (): MetadataState => ({
    metadata: [],
    loading: false,
    error: null,
    lastUpdated: null,
    initialized: false
  }),

  getters: {
    /**
     * Get metadata for all tables
     */
    allTables: (state): TableMetadata[] => state.metadata,

    /**
     * Get metadata for a specific table
     */
    getTableMetadata: (state) => (tableName: string): TableMetadata | undefined => {
      return state.metadata.find(meta => meta.table === tableName)
    },

    /**
     * Get total number of tables
     */
    totalTables: (state): number => state.metadata.length,

    /**
     * Get total number of records across all tables
     */
    totalRecords: (state): number => {
      return state.metadata.reduce((sum, meta) => sum + (meta.rowCount || 0), 0)
    },

    /**
     * Get list of all table names
     */
    tableNames: (state): string[] => {
      return state.metadata.map(meta => meta.table)
    },

    /**
     * Check if metadata is available
     */
    hasMetadata: (state): boolean => state.metadata.length > 0,

    /**
     * Check if metadata is currently loading
     */
    isLoading: (state): boolean => state.loading,

    /**
     * Check if there's an error
     */
    hasError: (state): boolean => !!state.error,

    /**
     * Get formatted last updated time
     */
    formattedLastUpdated: (state): string => {
      if (!state.lastUpdated) return 'Nunca'

      try {
        return new Date(state.lastUpdated).toLocaleString('es-ES', {
          year: 'numeric',
          month: 'long',
          day: 'numeric',
          hour: '2-digit',
          minute: '2-digit'
        })
      } catch {
        return 'Fecha inválida'
      }
    },

    /**
     * Check if metadata is stale (older than 5 minutes)
     */
    isStale: (state): boolean => {
      if (!state.lastUpdated) return true

      const lastUpdate = new Date(state.lastUpdated)
      const now = new Date()
      const fiveMinutes = 5 * 60 * 1000

      return (now.getTime() - lastUpdate.getTime()) > fiveMinutes
    }
  },

  actions: {
    /**
     * Load metadata lazily (only if not already loaded)
     */
    async loadMetadata(force = false): Promise<void> {
      // Don't load if already loading
      if (this.loading) return

      // Don't load if already initialized and not forced
      if (this.initialized && !force && !this.isStale) return

      await this.fetchMetadata()
    },

    /**
     * Force refresh metadata
     */
    async refreshMetadata(): Promise<void> {
      await this.fetchMetadata()
    },

    /**
     * Internal method to fetch metadata from API
     */
    async fetchMetadata(): Promise<void> {
      this.loading = true
      this.error = null

      try {
        const requestFetch = useRequestFetch()
        const response = await requestFetch('/api/metadata')

        if (Array.isArray(response)) {
          this.metadata = response.map((meta: any) => ({
            ...meta,
            lastRefreshed: meta.lastRefreshed || new Date().toISOString()
          }))
          this.lastUpdated = new Date().toISOString()
          this.initialized = true

          // Persist to localStorage for offline access
          if (process.client) {
            try {
              localStorage.setItem('metadata-cache', JSON.stringify({
                metadata: this.metadata,
                lastUpdated: this.lastUpdated
              }))
            } catch (error) {
              console.warn('Failed to persist metadata to localStorage:', error)
            }
          }
        } else {
          throw new Error('Invalid metadata response format')
        }
      } catch (error: any) {
        this.error = this.extractErrorMessage(error)
        console.error('Error fetching metadata:', error)

        // Try to load from cache if available
        if (process.client && !this.hasMetadata) {
          this.loadFromCache()
        }
      } finally {
        this.loading = false
      }
    },

    /**
     * Load metadata from localStorage cache
     */
    loadFromCache(): void {
      if (!process.client) return

      try {
        const cached = localStorage.getItem('metadata-cache')
        if (cached) {
          const parsedCache = JSON.parse(cached)
          this.metadata = parsedCache.metadata || []
          this.lastUpdated = parsedCache.lastUpdated || null
          this.initialized = true
        }
      } catch (error) {
        console.warn('Failed to load metadata from cache:', error)
      }
    },

    /**
     * Clear all metadata
     */
    clearMetadata(): void {
      this.metadata = []
      this.error = null
      this.lastUpdated = null
      this.initialized = false

      if (process.client) {
        try {
          localStorage.removeItem('metadata-cache')
        } catch (error) {
          console.warn('Failed to clear metadata cache:', error)
        }
      }
    },

    /**
     * Extract error message from various error types
     */
    extractErrorMessage(error: unknown): string {
      if (error && typeof error === 'object' && 'statusMessage' in error) {
        return String((error as { statusMessage: string }).statusMessage)
      }

      if (error instanceof Error) {
        return error.message
      }

      return 'Error inesperado al cargar metadatos'
    },

    /**
     * Initialize store (called on app startup)
     */
    async initialize(): Promise<void> {
      // Load from cache first for immediate availability
      this.loadFromCache()

      // Then try to fetch fresh data
      await this.loadMetadata()
    }
  },

  // Enable persistence for better UX
  persist: process.client ? {
    key: 'metadata-store',
    storage: localStorage,
    pick: ['metadata', 'lastUpdated', 'initialized']
  } : false
})