import { defineStore } from 'pinia'
import apiClient from '@data-entry/services/api'

// Create receipts-specific API wrapper
const api = {
  get: (url, config) => apiClient.get(`/receipts${url}`, config),
  post: (url, data, config) => apiClient.post(`/receipts${url}`, data, config),
  put: (url, data, config) => apiClient.put(`/receipts${url}`, data, config),
  delete: (url, config) => apiClient.delete(`/receipts${url}`, config),
}

export const useReceiptsStore = defineStore('receipts', {
  state: () => ({
    receipts: [],
    currentReceipt: null,
    pendingReceipts: [],
    stats: null,
    // Processing stats for bulk upload filtering (US-005)
    processingStats: {
      pending_count: 0,
      processing_count: 0,
      completed_count: 0,
      failed_count: 0,
    },
    loading: false,
    error: null,
    pagination: {
      page: 1,
      pageSize: 20,
      total: 0,
      pages: 1,
    },
    filters: {
      status: null,
      search: '',
      direction: null,
      dateFrom: null,
      dateTo: null,
      processingStatus: null, // US-005: Filter by processing_status
    },
    // Nomenclatures
    partners: [],
    accounts: [],
    cashRegisters: [],
    expenseTypes: [],
  }),

  getters: {
    hasReceipts: (state) => state.receipts.length > 0,
    hasPendingReceipts: (state) => state.pendingReceipts.length > 0,
    pendingCount: (state) => state.pendingReceipts.length,
  },

  actions: {
    // ============ Receipts CRUD ============

    async fetchReceipts() {
      this.loading = true
      this.error = null
      try {
        const params = {
          page: this.pagination.page,
          page_size: this.pagination.pageSize,
        }

        if (this.filters.status) {
          params.status = this.filters.status
        }
        if (this.filters.search) {
          params.search = this.filters.search
        }
        if (this.filters.direction) {
          params.direction = this.filters.direction
        }
        if (this.filters.dateFrom) {
          params.date_from = this.filters.dateFrom
        }
        if (this.filters.dateTo) {
          params.date_to = this.filters.dateTo
        }
        // US-005: Add processing_status filter
        // Map frontend filter values to backend values
        if (this.filters.processingStatus) {
          if (this.filters.processingStatus === 'in_processing') {
            // "În procesare" = pending + processing
            params.processing_status = 'pending,processing'
          } else {
            params.processing_status = this.filters.processingStatus
          }
        }

        const response = await api.get('/', { params })
        this.receipts = response.data.items
        this.pagination.total = response.data.total
        this.pagination.pages = response.data.pages
        // US-005: Capture processing_stats from API response
        if (response.data.processing_stats) {
          this.processingStats = response.data.processing_stats
        }
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to fetch receipts'
        throw error
      } finally {
        this.loading = false
      }
    },

    async fetchReceiptById(id) {
      this.loading = true
      this.error = null
      try {
        const response = await api.get(`/${id}`)
        this.currentReceipt = response.data
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to fetch receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    async createReceipt(data) {
      this.loading = true
      this.error = null
      try {
        const response = await api.post('/', data)
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to create receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    async updateReceipt(id, data) {
      this.loading = true
      this.error = null
      try {
        const response = await api.put(`/${id}`, data)
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to update receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    async deleteReceipt(id) {
      this.loading = true
      this.error = null
      try {
        await api.delete(`/${id}`)
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to delete receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    // ============ Workflow Actions ============

    async submitReceipt(id) {
      this.loading = true
      this.error = null
      try {
        const response = await api.post(`/${id}/submit`)
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to submit receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    async approveReceipt(id) {
      this.loading = true
      this.error = null
      try {
        const response = await api.post(`/${id}/approve`)
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to approve receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    async rejectReceipt(id, reason) {
      this.loading = true
      this.error = null
      try {
        const response = await api.post(`/${id}/reject`, { reason })
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to reject receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    async resubmitReceipt(id) {
      this.loading = true
      this.error = null
      try {
        const response = await api.post(`/${id}/resubmit`)
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to resubmit receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    async unapproveReceipt(id) {
      this.loading = true
      this.error = null
      try {
        const response = await api.post(`/${id}/unapprove`)
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to unapprove receipt'
        throw error
      } finally {
        this.loading = false
      }
    },

    // ============ Pending Receipts ============

    async fetchPendingReceipts() {
      this.loading = true
      this.error = null
      try {
        const response = await api.get('/pending')
        this.pendingReceipts = response.data
        return response.data
      } catch (error) {
        this.error = error.response?.data?.detail || 'Failed to fetch pending receipts'
        throw error
      } finally {
        this.loading = false
      }
    },

    // ============ Attachments ============

    async uploadAttachment(receiptId, file) {
      const formData = new FormData()
      formData.append('file', file)

      try {
        const response = await api.post(`/${receiptId}/attachments`, formData, {
          headers: { 'Content-Type': 'multipart/form-data' },
        })
        return response.data
      } catch (error) {
        throw new Error(error.response?.data?.detail || 'Failed to upload attachment')
      }
    },

    async deleteAttachment(attachmentId) {
      try {
        await api.delete(`/attachments/${attachmentId}`)
      } catch (error) {
        throw new Error(error.response?.data?.detail || 'Failed to delete attachment')
      }
    },

    getAttachmentUrl(attachmentId) {
      return `/api/data-entry/receipts/attachments/${attachmentId}/download`
    },

    async fetchAttachmentBlob(attachmentId) {
      try {
        // Use apiClient directly - attachments endpoints are at /api/receipts/attachments, not /api/receipts/receipts/attachments
        const response = await apiClient.get(`/receipts/attachments/${attachmentId}/download`, {
          responseType: 'blob',
        })
        return URL.createObjectURL(response.data)
      } catch (error) {
        console.error('Failed to fetch attachment:', error)
        return null
      }
    },

    async downloadAttachment(attachmentId, filename) {
      try {
        // Use apiClient directly - attachments endpoints are at /api/receipts/attachments, not /api/receipts/receipts/attachments
        const response = await apiClient.get(`/receipts/attachments/${attachmentId}/download`, {
          responseType: 'blob',
        })
        // Create download link
        const url = URL.createObjectURL(response.data)
        const link = document.createElement('a')
        link.href = url
        link.download = filename || 'attachment'
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        URL.revokeObjectURL(url)
        return true
      } catch (error) {
        console.error('Failed to download attachment:', error)
        throw new Error(error.response?.data?.detail || 'Failed to download attachment')
      }
    },

    // ============ Accounting Entries ============

    async fetchEntries(receiptId) {
      try {
        const response = await api.get(`/${receiptId}/entries`)
        return response.data
      } catch (error) {
        throw new Error(error.response?.data?.detail || 'Failed to fetch entries')
      }
    },

    async updateEntries(receiptId, entries) {
      try {
        const response = await api.put(`/${receiptId}/entries`, { entries })
        return response.data
      } catch (error) {
        throw new Error(error.response?.data?.detail || 'Failed to update entries')
      }
    },

    async regenerateEntries(receiptId) {
      try {
        const response = await api.post(`/${receiptId}/entries/regenerate`)
        return response.data
      } catch (error) {
        throw new Error(error.response?.data?.detail || 'Failed to regenerate entries')
      }
    },

    // ============ Nomenclatures ============

    async fetchPartners(search = '') {
      try {
        const response = await api.get('/nomenclature/partners', {
          params: { search },
        })
        this.partners = response.data
        return response.data
      } catch (error) {
        console.error('Failed to fetch partners:', error)
        return []
      }
    },

    async fetchAccounts(prefix = '') {
      try {
        const response = await api.get('/nomenclature/accounts', {
          params: { prefix },
        })
        this.accounts = response.data
        return response.data
      } catch (error) {
        console.error('Failed to fetch accounts:', error)
        return []
      }
    },

    async fetchCashRegisters() {
      try {
        const response = await api.get('/nomenclature/cash-registers')
        this.cashRegisters = response.data
        return response.data
      } catch (error) {
        console.error('Failed to fetch cash registers:', error)
        return []
      }
    },

    async fetchExpenseTypes() {
      try {
        const response = await api.get('/nomenclature/expense-types')
        this.expenseTypes = response.data
        return response.data
      } catch (error) {
        console.error('Failed to fetch expense types:', error)
        return []
      }
    },

    async fetchAllNomenclatures() {
      await Promise.all([
        this.fetchPartners(),
        this.fetchCashRegisters(),
        this.fetchExpenseTypes(),
      ])
    },

    async searchSupplier(fiscalCode) {
      try {
        // Use apiClient directly (not wrapped) - nomenclature endpoints are at /api/nomenclature, not /api/receipts
        const response = await apiClient.get('/nomenclature/suppliers/search', {
          params: { fiscal_code: fiscalCode },
        })
        return response.data
      } catch (error) {
        console.error('Supplier search failed:', error)
        return { found: false, source: 'error' }
      }
    },

    async createLocalSupplier(data) {
      try {
        // Use apiClient directly (not wrapped) - nomenclature endpoints are at /api/nomenclature, not /api/receipts
        const response = await apiClient.post('/nomenclature/suppliers/local', data)
        // Add to local partners list
        this.partners.push({
          id: response.data.id,
          name: response.data.name,
          fiscal_code: response.data.fiscal_code,
          address: response.data.address,
          source: 'local',
        })
        return response.data
      } catch (error) {
        throw new Error(error.response?.data?.detail || 'Failed to create supplier')
      }
    },

    async syncSuppliers() {
      try {
        // Use apiClient directly - nomenclature endpoints at /api/nomenclature
        const response = await apiClient.post('/nomenclature/sync/suppliers')
        console.log('[receiptsStore] Synced suppliers:', response.data)
        // Refresh partners list after sync
        await this.fetchPartners()
        return response.data
      } catch (error) {
        console.error('[receiptsStore] Supplier sync failed:', error)
        throw error
      }
    },

    // ============ Stats ============

    async fetchStats() {
      try {
        const response = await api.get('/stats')
        this.stats = response.data
        return response.data
      } catch (error) {
        console.error('Failed to fetch stats:', error)
        return null
      }
    },

    // ============ Retry Actions (US-006) ============

    /**
     * Retry processing for a single failed receipt.
     * Calls POST /bulk/retry/{receipt_id} to requeue the OCR job.
     *
     * @param {number} receiptId - Receipt ID to retry
     * @returns {Promise<{success: boolean, job_id: string, message: string}>}
     */
    async retryReceipt(receiptId) {
      try {
        // Use apiClient directly - bulk endpoints are at /api/data-entry/bulk, not /api/data-entry/receipts
        const response = await apiClient.post(`/bulk/retry/${receiptId}`)
        return response.data
      } catch (error) {
        const detail = error.response?.data?.detail || 'Eroare la reîncărcare'
        throw new Error(detail)
      }
    },

    /**
     * Retry all failed receipts in a batch.
     * Calls POST /bulk/retry-batch/{batch_id} to requeue all failed OCR jobs.
     *
     * @param {string} batchId - Batch ID (UUID string)
     * @returns {Promise<{success: boolean, retried_count: number, failed_count: number, message: string}>}
     */
    async retryBatchFailed(batchId) {
      try {
        // Use apiClient directly - bulk endpoints are at /api/data-entry/bulk, not /api/data-entry/receipts
        const response = await apiClient.post(`/bulk/retry-batch/${batchId}`)
        return response.data
      } catch (error) {
        const detail = error.response?.data?.detail || 'Eroare la reîncărcarea batch-ului'
        throw new Error(detail)
      }
    },

    // ============ Bulk Delete (US-027) ============

    /**
     * Bulk delete receipts by IDs.
     * Calls DELETE /receipts/bulk and returns partial success response.
     *
     * @param {number[]} ids - Array of receipt IDs to delete
     * @returns {Promise<{deleted: number[], failed: Array<{id: number, error: string}>}>}
     */
    async bulkDeleteReceipts(ids) {
      try {
        const response = await api.delete('/bulk', { data: { ids } })
        return response.data
      } catch (error) {
        const detail = error.response?.data?.detail || 'Eroare la ștergerea bonurilor'
        throw new Error(detail)
      }
    },

    /**
     * Remove receipts from local array by IDs (US-027).
     * Updates array in place without re-fetching from server.
     *
     * @param {number[]} ids - Array of receipt IDs to remove
     */
    removeReceiptsLocally(ids) {
      const idsSet = new Set(ids)
      this.receipts = this.receipts.filter(r => !idsSet.has(r.id))
    },

    /**
     * Update a single receipt in place without replacing the array (US-029).
     * Uses Object.assign() to preserve Vue reactivity and only re-render
     * the affected row, not the entire list.
     *
     * @param {number} receiptId - Receipt ID to update
     * @param {Object} updates - Object with properties to update
     * @returns {boolean} true if receipt was found and updated, false otherwise
     */
    updateReceiptInPlace(receiptId, updates) {
      const idx = this.receipts.findIndex(r => r.id === receiptId)
      if (idx !== -1) {
        Object.assign(this.receipts[idx], updates)
        return true
      }
      return false
    },

    /**
     * Insert a receipt in place at the correct position (US-034, US-043).
     *
     * US-043: Always prepend to maintain upload order. When jobs complete,
     * they transition from jobItems (prepended in unifiedItems) to receiptsList.
     * Prepending to receiptsList ensures the receipt appears where the job was -
     * right after the remaining pending jobs.
     *
     * This maintains visual position stability:
     * - Jobs are shown first (from batchProgressStore.jobs)
     * - As jobs complete, their receipts prepend to this.receipts
     * - Combined: [remaining_jobs] + [newly_completed_receipts] + [older_receipts]
     *
     * @param {Object} receipt - The full receipt object to insert
     * @returns {boolean} true if receipt was inserted
     */
    insertReceiptInPlace(receipt) {
      // Check if receipt already exists
      const existingIdx = this.receipts.findIndex(r => r.id === receipt.id)
      if (existingIdx !== -1) {
        // Already exists, update it instead (US-029: in-place update, no reordering)
        Object.assign(this.receipts[existingIdx], receipt)
        return true
      }

      // US-043: Always prepend new receipts to maintain upload order.
      // This preserves the position of completed jobs (which are prepended in unifiedItems).
      this.receipts.unshift(receipt)
      return true
    },

    // ============ Filters & Pagination ============

    setFilters(filters) {
      this.filters = { ...this.filters, ...filters }
      this.pagination.page = 1
    },

    clearFilters() {
      this.filters = {
        status: null,
        search: '',
        direction: null,
        dateFrom: null,
        dateTo: null,
        processingStatus: null, // US-005
      }
      this.pagination.page = 1
    },

    setPage(page) {
      this.pagination.page = page
    },

    clearCurrentReceipt() {
      this.currentReceipt = null
    },
  },
})
