/**
 * Pinia store for calendar feature — events, event types, tags,
 * invitations, and WebSocket event dispatch.
 *
 * ponytail: stores/chat.ts handleWsMessage dispatch is deferred — the
 * orchestrator will wire the 4 calendar_* WS cases to call handleWsEvent().
 * This store owns the calendar-specific state mutations + notifications.
 */

import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { notification } from 'ant-design-vue'
import { calendarApi, isCalendarEvent } from '@/api/calendar'
import type {
  ICalendarEvent,
  IEventType,
  ITag,
  IInvitation,
  ICreateEventRequest,
  IUpdateEventRequest,
  ICreateTagRequest,
  IUserSearchResult,
} from '@/api/calendar'
import type { WsServerMessage, ICalendarSyncConflictData } from '@/api/types'

export type CalendarViewMode = 'calendar' | 'card' | 'list'

export const useCalendarStore = defineStore('calendar', () => {
  // --- State ---
  const events = ref<ICalendarEvent[]>([])
  const eventTypes = ref<IEventType[]>([])
  const tags = ref<ITag[]>([])
  const isLoading = ref(false)
  const error = ref<string | null>(null)
  const selectedEvent = ref<ICalendarEvent | null>(null)
  const viewMode = ref<CalendarViewMode>('calendar')
  const dateRange = ref<{ start: string | null; end: string | null }>({
    start: null,
    end: null,
  })
  const pendingInvitations = ref<IInvitation[]>([])
  const syncConflicts = ref<ICalendarSyncConflictData[]>([])

  // --- Getters ---
  const upcomingEvents = computed(() => {
    const now = new Date().toISOString()
    return events.value
      .filter((e) => e.start_time >= now)
      .sort((a, b) => a.start_time.localeCompare(b.start_time))
  })

  // --- Actions ---

  /** Load events with current dateRange filter */
  async function loadEvents(): Promise<void> {
    isLoading.value = true
    error.value = null
    try {
      const resp = await calendarApi.listEvents(
        dateRange.value.start ?? undefined,
        dateRange.value.end ?? undefined,
      )
      events.value = resp.events || []
    } catch (err) {
      error.value = err instanceof Error ? err.message : '加载日程失败'
      console.warn('Failed to load calendar events:', err)
    } finally {
      isLoading.value = false
    }
  }

  /** Create a new event and add it to state */
  async function createEvent(data: ICreateEventRequest): Promise<ICalendarEvent | null> {
    isLoading.value = true
    error.value = null
    try {
      const resp = await calendarApi.createEvent(data)
      if (resp.event) {
        events.value.push(resp.event)
      }
      return resp.event ?? null
    } catch (err) {
      error.value = err instanceof Error ? err.message : '创建日程失败'
      console.error('Failed to create event:', err)
      throw err
    } finally {
      isLoading.value = false
    }
  }

  /** Update an existing event in state */
  async function updateEvent(id: string, data: IUpdateEventRequest): Promise<void> {
    error.value = null
    try {
      const resp = await calendarApi.updateEvent(id, data)
      if (resp.event) {
        const idx = events.value.findIndex((e) => e.id === id)
        if (idx !== -1) {
          events.value[idx] = resp.event
        }
      }
    } catch (err) {
      error.value = err instanceof Error ? err.message : '更新日程失败'
      console.error('Failed to update event:', err)
      throw err
    }
  }

  /** Delete an event from server and state */
  async function deleteEvent(id: string): Promise<void> {
    error.value = null
    try {
      await calendarApi.deleteEvent(id)
      events.value = events.value.filter((e) => e.id !== id)
    } catch (err) {
      error.value = err instanceof Error ? err.message : '删除日程失败'
      console.error('Failed to delete event:', err)
      throw err
    }
  }

  /** Load event types for the current user */
  async function loadEventTypes(): Promise<void> {
    try {
      const resp = await calendarApi.listEventTypes()
      eventTypes.value = resp.event_types || []
    } catch (err) {
      console.warn('Failed to load event types:', err)
    }
  }

  /** Load tags for the current user */
  async function loadTags(): Promise<void> {
    try {
      const resp = await calendarApi.listTags()
      tags.value = resp.tags || []
    } catch (err) {
      console.warn('Failed to load tags:', err)
    }
  }

  /** Create a new tag and add it to state */
  async function createTag(data: ICreateTagRequest): Promise<ITag | null> {
    try {
      const resp = await calendarApi.createTag(data)
      if (resp.tag) {
        tags.value.push(resp.tag)
      }
      return resp.tag ?? null
    } catch (err) {
      console.error('Failed to create tag:', err)
      throw err
    }
  }


  /** Set the calendar view mode */
  function setViewMode(mode: CalendarViewMode): void {
    viewMode.value = mode
  }

  /** Load pending invitations for the current user */
  async function loadInvitations(): Promise<void> {
    try {
      const resp = await calendarApi.listInvitations()
      pendingInvitations.value = (resp.invitations || []).filter(
        (i) => i.status === 'pending',
      )
    } catch (err) {
      console.warn('Failed to load invitations:', err)
    }
  }

  /** Respond to an invitation and remove it from pending list */
  async function respondToInvitation(
    id: string,
    status: 'accepted' | 'declined' | 'tentative',
  ): Promise<void> {
    try {
      await calendarApi.respondToInvitation(id, status)
      pendingInvitations.value = pendingInvitations.value.filter((i) => i.id !== id)
    } catch (err) {
      error.value = err instanceof Error ? err.message : '回复邀请失败'
      console.error('Failed to respond to invitation:', err)
      throw err
    }
  }

  /** Search users by username or email (G5/A3) */
  async function searchUsers(q: string): Promise<IUserSearchResult[]> {
    if (!q.trim()) return []
    try {
      const resp = await calendarApi.searchUsers(q)
      return resp.users || []
    } catch (err) {
      console.warn('Failed to search users:', err)
      return []
    }
  }

  /**
   * Dispatch calendar WS messages to the appropriate handler.
   * Handles 4 message types: calendar_event_created, calendar_reminder,
   * calendar_invitation (G6), calendar_sync_conflict (G4).
   * Non-calendar message types are silently ignored.
   */
  function handleWsEvent(msg: WsServerMessage): void {
    switch (msg.type) {
      case 'calendar_event_created': {
        const event = msg.data.event
        if (isCalendarEvent(event)) {
          // Avoid duplicates if the event was created locally
          if (!events.value.some((e) => e.id === event.id)) {
            events.value.push(event)
          }
        }
        break
      }
      case 'calendar_reminder': {
        const d = msg.data
        notification.warning({
          message: '日程提醒',
          description: `${d.title} · ${d.start_time}`,
          duration: 0,
        })
        break
      }
      case 'calendar_invitation': {
        const d = msg.data
        if (d.invitation) {
          pendingInvitations.value.push(d.invitation)
        }
        notification.info({
          message: '收到日程邀请',
          description: `${d.inviter_name} 邀请你参加「${d.event_title}」`,
          duration: 0,
        })
        break
      }
      case 'calendar_sync_conflict': {
        const d = msg.data
        syncConflicts.value.push(d)
        notification.warning({
          message: '日历同步冲突',
          description: `「${d.event_title}」与 ${d.provider} 同步冲突，已按 ${d.resolution} 策略处理`,
          duration: 0,
        })
        break
      }
    }
  }

  return {
    // State
    events,
    eventTypes,
    tags,
    isLoading,
    error,
    selectedEvent,
    viewMode,
    dateRange,
    pendingInvitations,
    syncConflicts,
    // Getters
    upcomingEvents,
    // Actions
    loadEvents,
    createEvent,
    updateEvent,
    deleteEvent,
    loadEventTypes,
    loadTags,
    createTag,
    setViewMode,
    loadInvitations,
    respondToInvitation,
    searchUsers,
    handleWsEvent,
  }
})
