/**
 * Memory System State Management (Zustand)
 */
import { create } from 'zustand'
import { memoryService, MemorySystem, TimelineEvent, PendingThread, CharacterState, Foreshadowing, Relationship, CreateThreadRequest, UpdateThreadRequest, CreateForeshadowingRequest, ImportanceLevel, MemoryStatistics } from '@/services/memoryService'

interface MemoryStore {
  // State
  projectId: string | null
  memorySystem: MemorySystem | null
  timeline: TimelineEvent[]
  threads: PendingThread[]
  characterStates: CharacterState[]
  foreshadowing: Foreshadowing[]
  relationships: Relationship[]
  statistics: MemoryStatistics | null

  loading: boolean
  error: string | null

  // Filters
  timelineFilters: {
    character?: string
    episode?: number
    importance?: ImportanceLevel
  }

  // Actions
  setProjectId: (projectId: string | null) => void
  fetchMemorySystem: (projectId: string) => Promise<void>
  fetchTimeline: (projectId: string, filters?: { character?: string; episode?: number; importance?: ImportanceLevel }) => Promise<void>
  fetchThreads: (projectId: string) => Promise<void>
  fetchCharacterStates: (projectId: string) => Promise<void>
  fetchForeshadowing: (projectId: string) => Promise<void>
  fetchRelationships: (projectId: string) => Promise<void>
  fetchStatistics: (projectId: string) => Promise<void>

  // Thread Actions
  createThread: (projectId: string, data: CreateThreadRequest) => Promise<PendingThread>
  updateThread: (projectId: string, threadId: string, data: UpdateThreadRequest) => Promise<void>
  deleteThread: (projectId: string, threadId: string) => Promise<void>
  resolveThread: (projectId: string, threadId: string) => Promise<void>

  // Foreshadowing Actions
  createForeshadowing: (projectId: string, data: CreateForeshadowingRequest) => Promise<Foreshadowing>
  updateForeshadowing: (projectId: string, foreshadowingId: string, data: any) => Promise<void>
  deleteForeshadowing: (projectId: string, foreshadowingId: string) => Promise<void>

  // Relationship Actions
  updateRelationship: (projectId: string, sourceCharacter: string, targetCharacter: string, data: any) => Promise<void>

  // Character Actions
  updateCharacterState: (projectId: string, characterName: string, state: string) => Promise<void>

  // Filter Actions
  setTimelineFilters: (filters: { character?: string; episode?: number; importance?: ImportanceLevel }) => void
  clearTimelineFilters: () => void

  // Clear
  clearMemory: () => void
}

export const useMemoryStore = create<MemoryStore>((set) => ({
  // Initial State with empty but structured data
  projectId: null,
  memorySystem: {
    projectId: '',
    timeline: [],
    pendingThreads: [],
    characterStates: [],
    foreshadowing: [],
    relationships: [],
    statistics: {
      totalEvents: 0,
      totalThreads: 0,
      resolvedThreads: 0,
      totalCharacters: 0,
      totalForeshadowing: 0,
      paidOffForeshadowing: 0,
      totalRelationships: 0
    }
  },
  timeline: [],
  threads: [],
  characterStates: [],
  foreshadowing: [],
  relationships: [],
  statistics: {
    totalEvents: 0,
    totalThreads: 0,
    resolvedThreads: 0,
    totalCharacters: 0,
    totalForeshadowing: 0,
    paidOffForeshadowing: 0,
    totalRelationships: 0
  },
  loading: false,
  error: null,
  timelineFilters: {},

  // Actions
  setProjectId: (projectId) => set({ projectId }),

  fetchMemorySystem: async (projectId) => {
    set({ loading: true, error: null, projectId })
    try {
      const memorySystem = await memoryService.getMemory(projectId)

      // Transform characterStates from dictionary to array format
      const characterStatesArray: CharacterState[] = memorySystem.characterStates
        ? Object.entries(memorySystem.characterStates).map(([characterName, stateChanges]: [string, any]) => ({
            characterName,
            currentState: stateChanges[stateChanges.length - 1]?.state || '',
            history: stateChanges
          }))
        : []

      // Transform relationships from nested dict to array format
      const relationshipsArray: Relationship[] = memorySystem.relationships
        ? Object.entries(memorySystem.relationships).flatMap(([sourceChar, targets]: [string, any]) =>
            Object.entries(targets).map(([targetChar, relationData]: [string, any]) => ({
              sourceCharacter: sourceChar,
              targetCharacter: targetChar,
              relationType: relationData.type || 'neutral',
              strength: relationData.strength || 50,
              description: relationData.description,
              evolutionHistory: relationData.history || []
            }))
          )
        : []

      // Transform timeline events to match frontend format
      const timelineArray: TimelineEvent[] = (memorySystem.timeline || []).map((event: any) => ({
        id: event.id || `${event.episode}_${event.timestamp}`,
        episodeNumber: event.episode || event.episodeNumber,
        timestamp: event.timestamp || event.createdAt,
        characters: event.characters_involved || event.characters || [],
        description: event.event || event.description,
        importance: event.importance || 'medium',
        category: event.tags?.[0] || event.category || 'general',
        createdAt: event.createdAt || event.timestamp
      }))

      // Transform threads to match frontend format
      const threadsArray: PendingThread[] = (memorySystem.pendingThreads || []).map((thread: any) => ({
        id: thread.id,
        description: thread.description,
        importance: thread.importance,
        status: thread.status || 'pending',
        reminderEpisode: thread.reminder_episode,
        relatedCharacters: thread.characters_involved || thread.relatedCharacters || [],
        createdAt: thread.created_at || thread.createdAt,
        resolvedAt: thread.resolved_at || thread.resolvedAt
      }))

      // Transform foreshadowing to match frontend format
      const foreshadowingArray: Foreshadowing[] = (memorySystem.foreshadowing || []).map((item: any) => ({
        id: item.id,
        description: item.description,
        importance: item.importance,
        payoffEventId: item.related_events?.[0],
        payoffEpisode: item.payoff_at,
        status: (item.is_payed_off ? 'paid_off' : 'planted') as 'paid_off' | 'planted',
        plantedEpisode: item.introduced_at,
        createdAt: item.createdAt || new Date().toISOString()
      }))

      // Transform statistics
      const statistics: MemoryStatistics = {
        totalEvents: timelineArray.length,
        totalThreads: threadsArray.length,
        resolvedThreads: threadsArray.filter((t: any) => t.status === 'resolved').length,
        totalCharacters: characterStatesArray.length,
        totalForeshadowing: foreshadowingArray.length,
        paidOffForeshadowing: foreshadowingArray.filter((f: any) => f.status === 'paid_off').length,
        totalRelationships: relationshipsArray.length
      }

      set({
        memorySystem,
        timeline: timelineArray,
        threads: threadsArray,
        characterStates: characterStatesArray,
        foreshadowing: foreshadowingArray,
        relationships: relationshipsArray,
        statistics,
        loading: false
      })
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  fetchTimeline: async (projectId, filters) => {
    set({ loading: true, error: null })
    try {
      const response = await memoryService.getTimeline(projectId, filters)
      // Transform to match frontend format
      const timelineArray = (response || []).map((event: any) => ({
        id: event.id || `${event.episode}_${event.timestamp}`,
        episodeNumber: event.episode || event.episodeNumber,
        timestamp: event.timestamp || event.createdAt,
        characters: event.characters_involved || event.characters || [],
        description: event.event || event.description,
        importance: event.importance || 'medium',
        category: event.tags?.[0] || event.category || 'general',
        createdAt: event.createdAt || event.timestamp
      }))
      set({ timeline: timelineArray, loading: false })
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  fetchThreads: async (projectId) => {
    set({ loading: true, error: null })
    try {
      const response = await memoryService.getThreads(projectId)
      // Transform to match frontend format
      const threadsArray = (response || []).map((thread: any) => ({
        id: thread.id,
        description: thread.description,
        importance: thread.importance,
        status: thread.status || 'pending',
        reminderEpisode: thread.reminder_episode,
        relatedCharacters: thread.characters_involved || thread.relatedCharacters || [],
        createdAt: thread.created_at || thread.createdAt,
        resolvedAt: thread.resolved_at || thread.resolvedAt
      }))
      set({ threads: threadsArray, loading: false })
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  fetchCharacterStates: async (projectId) => {
    set({ loading: true, error: null })
    try {
      const response = await memoryService.getCharacterStates(projectId)
      // Transform from dict to array format
      const characterStatesArray = response
        ? Object.entries(response).map(([characterName, stateChanges]: [string, any]) => ({
            characterName,
            currentState: stateChanges[stateChanges.length - 1]?.state || '',
            history: stateChanges
          }))
        : []
      set({ characterStates: characterStatesArray, loading: false })
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  fetchForeshadowing: async (projectId) => {
    set({ loading: true, error: null })
    try {
      const response = await memoryService.getForeshadowing(projectId)
      // Transform to match frontend format
      const foreshadowingArray: Foreshadowing[] = (response || []).map((item: any) => ({
        id: item.id,
        description: item.description,
        importance: item.importance,
        payoffEventId: item.related_events?.[0],
        payoffEpisode: item.payoff_at,
        status: (item.is_payed_off ? 'paid_off' : 'planted') as 'paid_off' | 'planted',
        plantedEpisode: item.introduced_at,
        createdAt: item.createdAt || new Date().toISOString()
      }))
      set({ foreshadowing: foreshadowingArray, loading: false })
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  fetchRelationships: async (projectId) => {
    set({ loading: true, error: null })
    try {
      const response = await memoryService.getRelationships(projectId)
      // Transform from nested dict to array format
      const relationshipsArray: Relationship[] = response
        ? Object.entries(response).flatMap(([sourceChar, targets]: [string, any]) =>
            Object.entries(targets).map(([targetChar, relationData]: [string, any]) => ({
              sourceCharacter: sourceChar,
              targetCharacter: targetChar,
              relationType: relationData.type || 'neutral',
              strength: relationData.strength || 50,
              description: relationData.description,
              evolutionHistory: relationData.history || []
            }))
          )
        : []
      set({ relationships: relationshipsArray, loading: false })
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  fetchStatistics: async (projectId) => {
    set({ loading: true, error: null })
    try {
      const statistics = await memoryService.getStatistics(projectId)
      set({ statistics: statistics as MemoryStatistics, loading: false })
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  // Thread Actions
  createThread: async (projectId, data) => {
    set({ loading: true, error: null })
    try {
      const thread = await memoryService.createThread(projectId, data)
      set((state) => ({
        threads: [...state.threads, thread],
        loading: false
      }))
      return thread
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
      throw error
    }
  },

  updateThread: async (projectId, threadId, data) => {
    set({ loading: true, error: null })
    try {
      const updatedThread = await memoryService.updateThread(projectId, threadId, data)
      set((state) => ({
        threads: state.threads.map(t => t.id === threadId ? updatedThread : t),
        loading: false
      }))
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  deleteThread: async (projectId, threadId) => {
    set({ loading: true, error: null })
    try {
      await memoryService.deleteThread(projectId, threadId)
      set((state) => ({
        threads: state.threads.filter(t => t.id !== threadId),
        loading: false
      }))
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  resolveThread: async (projectId, threadId) => {
    set({ loading: true, error: null })
    try {
      const resolvedThread = await memoryService.resolveThread(projectId, threadId)
      set((state) => ({
        threads: state.threads.map(t => t.id === threadId ? resolvedThread : t),
        loading: false
      }))
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  // Foreshadowing Actions
  createForeshadowing: async (projectId, data) => {
    set({ loading: true, error: null })
    try {
      const foreshadowing = await memoryService.createForeshadowing(projectId, data)
      set((state) => ({
        foreshadowing: [...state.foreshadowing, foreshadowing],
        loading: false
      }))
      return foreshadowing
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
      throw error
    }
  },

  updateForeshadowing: async (projectId, foreshadowingId, data) => {
    set({ loading: true, error: null })
    try {
      const updated = await memoryService.updateForeshadowing(projectId, foreshadowingId, data)
      set((state) => ({
        foreshadowing: state.foreshadowing.map(f => f.id === foreshadowingId ? updated : f),
        loading: false
      }))
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  deleteForeshadowing: async (projectId, foreshadowingId) => {
    set({ loading: true, error: null })
    try {
      await memoryService.deleteForeshadowing(projectId, foreshadowingId)
      set((state) => ({
        foreshadowing: state.foreshadowing.filter(f => f.id !== foreshadowingId),
        loading: false
      }))
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  // Relationship Actions
  updateRelationship: async (projectId, sourceCharacter, targetCharacter, data) => {
    set({ loading: true, error: null })
    try {
      const updated = await memoryService.updateRelationship(projectId, sourceCharacter, targetCharacter, data)
      set((state) => ({
        relationships: state.relationships.map(r =>
          r.sourceCharacter === sourceCharacter && r.targetCharacter === targetCharacter ? updated : r
        ),
        loading: false
      }))
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  // Character Actions
  updateCharacterState: async (projectId, characterName, state) => {
    set({ loading: true, error: null })
    try {
      const updated = await memoryService.updateCharacterState(projectId, characterName, state)
      set((state) => ({
        characterStates: state.characterStates.map(cs =>
          cs.characterName === characterName ? updated : cs
        ),
        loading: false
      }))
    } catch (error) {
      set({ error: (error as Error).message, loading: false })
    }
  },

  // Filter Actions
  setTimelineFilters: (filters) => set({ timelineFilters: filters }),

  clearTimelineFilters: () => set({ timelineFilters: {} }),

  // Clear
  clearMemory: () => set({
    projectId: null,
    memorySystem: null,
    timeline: [],
    threads: [],
    characterStates: [],
    foreshadowing: [],
    relationships: [],
    statistics: null,
    error: null,
    timelineFilters: {}
  })
}))
