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

export interface Expense {
  id?: number
  project_id: number
  client_id?: number
  category: string
  description?: string
  amount: number
  date: string
  receipt_path?: string
  invoiced?: number
}

export const EXPENSE_CATEGORIES = [
  { label: 'Materials', value: 'materials' },
  { label: 'Software', value: 'software' },
  { label: 'Travel', value: 'travel' },
  { label: 'Meals', value: 'meals' },
  { label: 'Equipment', value: 'equipment' },
  { label: 'Subcontractor', value: 'subcontractor' },
  { label: 'Communication', value: 'communication' },
  { label: 'Office', value: 'office' },
  { label: 'Other', value: 'other' },
]

export const useExpensesStore = defineStore('expenses', () => {
  const expenses = ref<Expense[]>([])
  const loading = ref(false)

  async function fetchExpenses(projectId?: number, startDate?: string, endDate?: string) {
    loading.value = true
    try {
      expenses.value = await invoke<Expense[]>('get_expenses', {
        projectId: projectId || null,
        startDate: startDate || null,
        endDate: endDate || null
      })
    } catch (error) {
      handleInvokeError(error, 'Failed to fetch expenses', () => fetchExpenses(projectId, startDate, endDate))
    } finally {
      loading.value = false
    }
  }

  async function createExpense(expense: Expense): Promise<number | null> {
    try {
      const id = await invoke<number>('create_expense', { expense })
      expenses.value.unshift({ ...expense, id: Number(id) })
      return Number(id)
    } catch (error) {
      handleInvokeError(error, 'Failed to create expense')
      return null
    }
  }

  async function updateExpense(expense: Expense): Promise<boolean> {
    try {
      await invoke('update_expense', { expense })
      const index = expenses.value.findIndex(e => e.id === expense.id)
      if (index !== -1) {
        expenses.value[index] = expense
      }
      return true
    } catch (error) {
      handleInvokeError(error, 'Failed to update expense')
      return false
    }
  }

  async function deleteExpense(id: number): Promise<boolean> {
    try {
      await invoke('delete_expense', { id })
      expenses.value = expenses.value.filter(e => e.id !== id)
      return true
    } catch (error) {
      handleInvokeError(error, 'Failed to delete expense')
      return false
    }
  }

  async function fetchUninvoiced(projectId?: number, clientId?: number): Promise<Expense[]> {
    try {
      return await invoke<Expense[]>('get_uninvoiced_expenses', {
        projectId: projectId || null,
        clientId: clientId || null
      })
    } catch (error) {
      handleInvokeError(error, 'Failed to fetch uninvoiced expenses')
      return []
    }
  }

  async function markInvoiced(ids: number[]): Promise<boolean> {
    try {
      await invoke('mark_expenses_invoiced', { ids })
      for (const id of ids) {
        const index = expenses.value.findIndex(e => e.id === id)
        if (index !== -1) {
          expenses.value[index].invoiced = 1
        }
      }
      return true
    } catch (error) {
      handleInvokeError(error, 'Failed to mark expenses as invoiced')
      return false
    }
  }

  return {
    expenses,
    loading,
    fetchExpenses,
    createExpense,
    updateExpense,
    deleteExpense,
    fetchUninvoiced,
    markInvoiced
  }
})
