import { defineStore } from 'pinia'
import { ref } from 'vue'
import type {
  Document,
  Tag,
  DocumentReasoning,
  ReasoningStep,
  ReasoningPanelData,
  TipTapContentResponse,
  BacklinksResponse,
  OutgoingLinksResponse,
  DocumentLinksResponse,
  SearchResponse
} from '@/types'
import { useApi, getToken } from '@/composables/useApi'

export const useDocumentsStore = defineStore('documents', () => {
  const currentDocument = ref<Document | null>(null)
  const tags = ref<Tag[]>([])
  const loading = ref(false)
  const error = ref<string | null>(null)
  const saving = ref(false)

  const api = useApi()

  async function fetchDocument(id: string) {
    loading.value = true
    error.value = null
    try {
      currentDocument.value = await api.get<Document>(`/documents/${id}`)
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'Failed to fetch document'
      throw e
    } finally {
      loading.value = false
    }
  }

  async function createDocument(projectId: string, title: string, content: string = '', folderId: string | null = null) {
    const body: { title: string; content: string; folder_id?: string } = { title, content }
    if (folderId) {
      body.folder_id = folderId
    }
    const doc = await api.post<Document>(`/projects/${projectId}/documents`, body)
    
    // Refresh current project tree if needed
    return doc
  }

  async function updateDocument(id: string, title: string, folderId?: string | null) {
    const body: { title: string; folder_id?: string | null } = { title }
    if (folderId !== undefined) {
      body.folder_id = folderId
    }
    const doc = await api.put<Document>(`/documents/${id}`, body)
    if (currentDocument.value?.id === id) {
      currentDocument.value = doc
    }
    return doc
  }

  async function updateDocumentContent(id: string, content: string) {
    saving.value = true
    try {
      await api.put(`/documents/${id}/content`, { content })
      if (currentDocument.value?.id === id) {
        currentDocument.value.content = content
      }
    } finally {
      saving.value = false
    }
  }

  async function deleteDocument(id: string) {
    await api.delete(`/documents/${id}`)
    if (currentDocument.value?.id === id) {
      currentDocument.value = null
    }
  }

  async function fetchTags() {
    try {
      tags.value = await api.get<Tag[]>('/tags')
    } catch (e) {
      console.error('Failed to fetch tags:', e)
    }
  }

  async function createTag(name: string, color: string) {
    const tag = await api.post<Tag>('/tags', { name, color })
    tags.value.push(tag)
    return tag
  }

  async function assignTags(documentId: string, tagIds: string[]) {
    await api.put(`/documents/${documentId}/tags`, { tag_ids: tagIds })
    if (currentDocument.value?.id === documentId) {
      currentDocument.value.tags = tags.value.filter(t => tagIds.includes(t.id))
    }
  }

  async function removeTag(documentId: string, tagId: string) {
    await api.delete(`/documents/${documentId}/tags/${tagId}`)
    if (currentDocument.value?.id === documentId) {
      currentDocument.value.tags = currentDocument.value.tags.filter(t => t.id !== tagId)
    }
  }

  async function updateDocumentTipTapContent(id: string, tiptapContent: Record<string, unknown>) {
    saving.value = true
    try {
      await api.put(`/documents/${id}/content`, {
        content: tiptapContent,
        format: 'tiptap'
      })
      if (currentDocument.value?.id === id) {
        currentDocument.value.tiptap_content = tiptapContent
      }
    } finally {
      saving.value = false
    }
  }

  async function fetchTipTapContent(id: string): Promise<Record<string, unknown> | null> {
    try {
      const response = await api.get<TipTapContentResponse>(`/documents/${id}/content?format=tiptap`)
      return response.content
    } catch {
      return null
    }
  }

  async function fetchReasoningPanel(id: string): Promise<ReasoningPanelData | null> {
    try {
      return await api.get<ReasoningPanelData>(`/documents/${id}/reasoning-panel`)
    } catch {
      return null
    }
  }

  async function updateReasoning(id: string, reasoning: Partial<DocumentReasoning>) {
    const updated = await api.put<DocumentReasoning>(`/documents/${id}/reasoning`, reasoning)
    if (currentDocument.value?.id === id) {
      currentDocument.value.reasoning = updated
    }
    return updated
  }

  async function addReasoningStep(documentId: string, thought: string, conclusion: string | null): Promise<ReasoningStep | null> {
    try {
      return await api.post<ReasoningStep>(`/documents/${documentId}/reasoning-steps`, { thought, conclusion })
    } catch {
      return null
    }
  }

  async function deleteReasoningStep(documentId: string, step: number) {
    await api.delete(`/documents/${documentId}/reasoning-steps/${step}`)
  }

  // Phase 3: Backlinks & Links
  async function fetchBacklinks(documentId: string): Promise<BacklinksResponse> {
    return await api.get<BacklinksResponse>(`/documents/${documentId}/backlinks`)
  }

  async function fetchOutgoingLinks(documentId: string): Promise<OutgoingLinksResponse> {
    return await api.get<OutgoingLinksResponse>(`/documents/${documentId}/outgoing-links`)
  }

  async function fetchDocumentLinks(documentId: string): Promise<DocumentLinksResponse> {
    return await api.get<DocumentLinksResponse>(`/documents/${documentId}/links`)
  }

  // Phase 3: Search
  async function search(query: string, type = 'documents', limit = 10, projectId?: string): Promise<SearchResponse> {
    const params = new URLSearchParams({ q: query, type, limit: String(limit) })
    if (projectId) params.set('project_id', projectId)
    return await api.get<SearchResponse>(`/search?${params}`)
  }

  // Phase 3: Export
  async function exportDocument(documentId: string, format: 'markdown' | 'json'): Promise<Blob> {
    const BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api/v1'
    // Use raw fetch to handle binary response
    const response = await fetch(`${BASE_URL}/documents/${documentId}/export?format=${format}`, {
      headers: {
        'Authorization': `Bearer ${getToken()}`
      },
      credentials: 'include'
    })
    if (!response.ok) throw new Error('Export failed')
    return await response.blob()
  }

  return {
    currentDocument,
    tags,
    loading,
    error,
    saving,
    fetchDocument,
    createDocument,
    updateDocument,
    updateDocumentContent,
    updateDocumentTipTapContent,
    fetchTipTapContent,
    fetchReasoningPanel,
    updateReasoning,
    addReasoningStep,
    deleteReasoningStep,
    deleteDocument,
    fetchTags,
    createTag,
    assignTags,
    removeTag,
    // Phase 3
    fetchBacklinks,
    fetchOutgoingLinks,
    fetchDocumentLinks,
    search,
    exportDocument
  }
})
