import { defineStore } from 'pinia'
import { ref } from 'vue'
import { invoke } from '@tauri-apps/api/core'
import { useToastStore } from './toast'
import { useTimerStore } from './timer'
import { handleInvokeError } from '../utils/errorHandler'

export interface RecurringEntry {
  id?: number
  project_id: number
  task_id?: number
  description?: string
  duration: number
  recurrence_rule: string  // "daily", "weekdays", "weekly:mon,wed,fri", "monthly:15"
  time_of_day: string      // "09:00"
  mode: 'auto_create' | 'prompt' | 'prefill_timer'
  enabled?: number         // 1 = enabled, 0 = disabled
  last_triggered?: string  // ISO date string
}

export const useRecurringStore = defineStore('recurring', () => {
  const entries = ref<RecurringEntry[]>([])
  const pendingPrompt = ref<RecurringEntry | null>(null)
  const snoozedUntil = ref<Map<number, number>>(new Map())

  async function fetchEntries() {
    try {
      entries.value = await invoke<RecurringEntry[]>('get_recurring_entries')
    } catch (e) {
      handleInvokeError(e, 'Failed to fetch recurring entries', () => fetchEntries())
    }
  }

  async function createEntry(entry: RecurringEntry) {
    try {
      const id = await invoke<number>('create_recurring_entry', { entry })
      await fetchEntries()
      return id
    } catch (e) {
      handleInvokeError(e, 'Failed to create recurring entry')
      throw e
    }
  }

  async function updateEntry(entry: RecurringEntry) {
    try {
      await invoke('update_recurring_entry', { entry })
      await fetchEntries()
    } catch (e) {
      handleInvokeError(e, 'Failed to update recurring entry')
      throw e
    }
  }

  async function deleteEntry(id: number) {
    try {
      await invoke('delete_recurring_entry', { id })
      await fetchEntries()
    } catch (e) {
      handleInvokeError(e, 'Failed to delete recurring entry')
      throw e
    }
  }

  async function toggleEnabled(entry: RecurringEntry) {
    const updated = { ...entry, enabled: entry.enabled === 1 ? 0 : 1 }
    await updateEntry(updated)
  }

  // Core recurrence check engine
  async function checkRecurrences() {
    if (entries.value.length === 0) return

    const now = new Date()
    const todayStr = now.toISOString().split('T')[0]  // YYYY-MM-DD
    const currentTime = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`
    const dayOfWeek = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][now.getDay()]
    const dayOfMonth = now.getDate()

    for (const entry of entries.value) {
      if (entry.enabled === 0) continue

      // Check if already triggered today
      if (entry.last_triggered) {
        const lastDate = entry.last_triggered.split('T')[0]
        if (lastDate === todayStr) continue
      }

      // Check if current time has passed the scheduled time
      if (currentTime < entry.time_of_day) continue

      // Check recurrence rule
      const rule = entry.recurrence_rule
      let shouldFire = false

      if (rule === 'daily') {
        shouldFire = true
      } else if (rule === 'weekdays') {
        shouldFire = !['sat', 'sun'].includes(dayOfWeek)
      } else if (rule.startsWith('weekly:')) {
        const days = rule.replace('weekly:', '').split(',')
        shouldFire = days.includes(dayOfWeek)
      } else if (rule.startsWith('monthly:')) {
        const targetDay = parseInt(rule.replace('monthly:', ''))
        shouldFire = dayOfMonth === targetDay
      }

      if (!shouldFire) continue

      // Check snooze: skip if snoozed and not yet expired
      if (entry.id && snoozedUntil.value.has(entry.id)) {
        if (Date.now() < snoozedUntil.value.get(entry.id)!) continue
        snoozedUntil.value.delete(entry.id)
      }

      // Fire the recurrence based on mode
      await fireRecurrence(entry)
    }
  }

  async function fireRecurrence(entry: RecurringEntry) {
    const toastStore = useToastStore()

    if (entry.mode === 'auto_create') {
      // Silently create a time entry
      const now = new Date()
      const startTime = new Date(now)
      const [h, m] = entry.time_of_day.split(':').map(Number)
      startTime.setHours(h, m, 0, 0)
      const endTime = new Date(startTime.getTime() + entry.duration * 1000)

      try {
        await invoke('create_time_entry', {
          entry: {
            project_id: entry.project_id,
            task_id: entry.task_id || null,
            description: entry.description || null,
            start_time: startTime.toISOString(),
            end_time: endTime.toISOString(),
            duration: entry.duration,
            billable: 1,
          }
        })
        toastStore.success('Recurring entry created')
      } catch (e) {
        console.error('Failed to auto-create recurring entry:', e)
      }
    } else if (entry.mode === 'prompt') {
      pendingPrompt.value = entry
    } else if (entry.mode === 'prefill_timer') {
      // Pre-fill the timer with project/task/description
      const timerStore = useTimerStore()
      if (timerStore.isStopped) {
        timerStore.setProject(entry.project_id)
        if (entry.task_id) timerStore.setTask(entry.task_id)
        if (entry.description) timerStore.setDescription(entry.description)
        toastStore.info('Timer pre-filled from recurring entry')
      }
    }

    // Mark as triggered today (skip for prompt mode - user action handlers do it)
    if (entry.mode !== 'prompt' && entry.id) {
      await markTriggered(entry.id)
    }
  }

  async function markTriggered(id: number) {
    try {
      await invoke('update_recurring_last_triggered', {
        id,
        lastTriggered: new Date().toISOString(),
      })
      const idx = entries.value.findIndex(e => e.id === id)
      if (idx !== -1) {
        entries.value[idx].last_triggered = new Date().toISOString()
      }
    } catch (e) {
      console.error('Failed to update last_triggered:', e)
    }
  }

  function snoozePrompt() {
    const entry = pendingPrompt.value
    if (entry?.id) {
      snoozedUntil.value.set(entry.id, Date.now() + 30 * 60 * 1000)
    }
    pendingPrompt.value = null
  }

  async function confirmPrompt() {
    if (!pendingPrompt.value) return
    const entry = pendingPrompt.value
    const now = new Date()
    const [h, m] = entry.time_of_day.split(':').map(Number)
    const startTime = new Date(now)
    startTime.setHours(h, m, 0, 0)
    const endTime = new Date(startTime.getTime() + entry.duration * 1000)

    try {
      await invoke('create_time_entry', {
        entry: {
          project_id: entry.project_id,
          task_id: entry.task_id || null,
          description: entry.description || null,
          start_time: startTime.toISOString(),
          end_time: endTime.toISOString(),
          duration: entry.duration,
          billable: 1,
        }
      })
      const toastStore = useToastStore()
      toastStore.success('Recurring entry created')
      if (entry.id) await markTriggered(entry.id)
    } catch (e) {
      handleInvokeError(e, 'Failed to create recurring entry')
    }
    pendingPrompt.value = null
  }

  async function skipPrompt() {
    const entry = pendingPrompt.value
    if (entry?.id) {
      await markTriggered(entry.id)
    }
    pendingPrompt.value = null
  }

  return { entries, pendingPrompt, fetchEntries, createEntry, updateEntry, deleteEntry, toggleEnabled, checkRecurrences, snoozePrompt, confirmPrompt, skipPrompt }
})
