import { ref } from 'vue'
import { apiFetch } from '@/lib/tauri'
import type { GitStatus, CommitInfo, FileDiff, BranchInfo, CompareResult, DiffResult, TreeNode, FileContent } from '@/types/git'

const API_BASE = '/api/git'

export function useGitApi() {
  const status = ref<GitStatus | null>(null)
  const commits = ref<CommitInfo[]>([])
  const branches = ref<BranchInfo[]>([])
  const currentBranch = ref<string>('')
  const diff = ref<DiffResult | null>(null)
  const compareResult = ref<CompareResult | null>(null)
  const selectedCommit = ref<CommitInfo | null>(null)
  const fileTree = ref<TreeNode[]>([])
  const fileContent = ref<FileContent | null>(null)
  const loading = ref(false)
  const error = ref<string | null>(null)

  async function fetchStatus() {
    loading.value = true
    error.value = null
    try {
      const res = await apiFetch(`${API_BASE}/status`)
      if (!res.ok) throw new Error('Failed to fetch status')
      status.value = await res.json()
      currentBranch.value = status.value?.branch || ''
    } catch (e: any) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }

  async function fetchDiff(options?: { staged?: boolean; file?: string }) {
    loading.value = true
    error.value = null
    try {
      const params = new URLSearchParams()
      if (options?.staged) params.set('staged', 'true')
      if (options?.file) params.set('file', options.file)

      const res = await apiFetch(`${API_BASE}/diff?${params}`)
      if (!res.ok) throw new Error('Failed to fetch diff')
      diff.value = await res.json()
    } catch (e: any) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }

  async function fetchLog(limit = 50, offset = 0, append = false) {
    loading.value = true
    error.value = null
    try {
      const res = await apiFetch(`${API_BASE}/log?limit=${limit}&offset=${offset}`)
      if (!res.ok) throw new Error('Failed to fetch log')
      const data = await res.json()
      commits.value = append ? [...commits.value, ...data] : data
    } catch (e: any) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }

  async function fetchCommit(sha: string) {
    loading.value = true
    error.value = null
    try {
      const res = await apiFetch(`${API_BASE}/log/${sha}`)
      if (!res.ok) throw new Error('Failed to fetch commit')
      selectedCommit.value = await res.json()
    } catch (e: any) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }

  async function fetchBranches() {
    error.value = null
    try {
      const res = await apiFetch(`${API_BASE}/branches`)
      if (!res.ok) throw new Error('Failed to fetch branches')
      branches.value = await res.json()
    } catch (e: any) {
      error.value = e.message
    }
  }

  async function compare(base: string, head: string) {
    loading.value = true
    error.value = null
    try {
      const res = await apiFetch(`${API_BASE}/compare`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ base, head })
      })
      if (!res.ok) {
        const err = await res.json()
        throw new Error(err.error || 'Failed to compare')
      }
      compareResult.value = await res.json()
    } catch (e: any) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }

  function clearDiff() {
    diff.value = null
  }

  function clearCompare() {
    compareResult.value = null
  }

  async function fetchFileTree(path?: string) {
    loading.value = true
    error.value = null
    try {
      const params = new URLSearchParams()
      if (path) params.set('path', path)

      const res = await apiFetch(`${API_BASE}/tree?${params}`)
      if (!res.ok) throw new Error('Failed to fetch file tree')
      fileTree.value = await res.json()
    } catch (e: any) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }

  async function fetchFileContent(path: string) {
    loading.value = true
    error.value = null
    try {
      const params = new URLSearchParams({ path })
      const res = await apiFetch(`${API_BASE}/file?${params}`)
      if (!res.ok) throw new Error('Failed to fetch file content')
      fileContent.value = await res.json()
    } catch (e: any) {
      error.value = e.message
    } finally {
      loading.value = false
    }
  }

  function clearFileContent() {
    fileContent.value = null
  }

  return {
    status,
    commits,
    branches,
    currentBranch,
    diff,
    compareResult,
    selectedCommit,
    fileTree,
    fileContent,
    loading,
    error,
    fetchStatus,
    fetchDiff,
    fetchLog,
    fetchCommit,
    fetchBranches,
    compare,
    clearDiff,
    clearCompare,
    fetchFileTree,
    fetchFileContent,
    clearFileContent
  }
}
