import { useState, useCallback } from 'react'
import { branchesApi } from '@/api/branches'
import { toast } from '@/lib/toast'
import type {
  BranchResponse,
  ForkCreateRequest,
  ForkPointResponse,
  BranchSwitchResponse,
  ReviveRequest,
  BranchMessageRequest,
  BranchMessageResponse,
} from '@/types/branching'

export interface UseBranching {
  // State
  branches: BranchResponse[]
  activeBranchId: string | null
  isLoading: boolean
  isProcessing: boolean

  // Actions
  loadBranches: (sessionId: string) => Promise<void>
  createFork: (sessionId: string, data: ForkCreateRequest) => Promise<ForkPointResponse | null>
  switchBranch: (sessionId: string, branchId: string) => Promise<BranchSwitchResponse | null>
  updateStatus: (sessionId: string, branchId: string, status: string, reason?: string) => Promise<void>
  reviveBranch: (sessionId: string, branchId: string, data: ReviveRequest) => Promise<void>
  sendMessage: (sessionId: string, branchId: string, data: BranchMessageRequest) => Promise<BranchMessageResponse | null>
}

export function useBranching(): UseBranching {
  const [branches, setBranches] = useState<BranchResponse[]>([])
  const [activeBranchId, setActiveBranchId] = useState<string | null>(null)
  const [isLoading, setIsLoading] = useState(false)
  const [isProcessing, setIsProcessing] = useState(false)

  const loadBranches = useCallback(async (sessionId: string) => {
    setIsLoading(true)
    try {
      const result = await branchesApi.getBranches(sessionId)
      setBranches(result.branches)
      setActiveBranchId(result.active_branch_id)
    } catch {
      toast.error('Failed to load branches')
    } finally {
      setIsLoading(false)
    }
  }, [])

  const createFork = useCallback(async (
    sessionId: string,
    data: ForkCreateRequest
  ): Promise<ForkPointResponse | null> => {
    setIsProcessing(true)
    try {
      const result = await branchesApi.createFork(sessionId, data)
      // Reload branches to reflect the new fork
      const updated = await branchesApi.getBranches(sessionId)
      setBranches(updated.branches)
      setActiveBranchId(updated.active_branch_id)
      return result
    } catch {
      toast.error('Failed to create fork')
      return null
    } finally {
      setIsProcessing(false)
    }
  }, [])

  const switchBranch = useCallback(async (
    sessionId: string,
    branchId: string
  ): Promise<BranchSwitchResponse | null> => {
    setIsProcessing(true)
    try {
      const result = await branchesApi.switchBranch(sessionId, branchId)
      setActiveBranchId(result.active_branch_id)
      setBranches(prev =>
        prev.map(b => b.id === result.active_branch_id ? result.branch : b)
      )
      return result
    } catch {
      toast.error('Failed to switch branch')
      return null
    } finally {
      setIsProcessing(false)
    }
  }, [])

  const updateStatus = useCallback(async (
    sessionId: string,
    branchId: string,
    status: string,
    reason?: string
  ) => {
    setIsProcessing(true)
    try {
      await branchesApi.updateBranchStatus(sessionId, branchId, status, reason)
      setBranches(prev =>
        prev.map(b =>
          b.id === branchId
            ? { ...b, status: status as BranchResponse['status'], status_reason: reason ?? b.status_reason }
            : b
        )
      )
    } catch {
      toast.error('Failed to update branch status')
    } finally {
      setIsProcessing(false)
    }
  }, [])

  const reviveBranch = useCallback(async (
    sessionId: string,
    branchId: string,
    data: ReviveRequest
  ) => {
    setIsProcessing(true)
    try {
      await branchesApi.reviveBranch(sessionId, branchId, data)
      // Reload to get updated statuses
      const updated = await branchesApi.getBranches(sessionId)
      setBranches(updated.branches)
      setActiveBranchId(updated.active_branch_id)
      toast.success('Branch revived')
    } catch {
      toast.error('Failed to revive branch')
    } finally {
      setIsProcessing(false)
    }
  }, [])

  const sendMessage = useCallback(async (
    sessionId: string,
    branchId: string,
    data: BranchMessageRequest
  ): Promise<BranchMessageResponse | null> => {
    setIsProcessing(true)
    try {
      const result = await branchesApi.sendBranchMessage(sessionId, branchId, data)
      return result
    } catch {
      toast.error('Failed to send message')
      return null
    } finally {
      setIsProcessing(false)
    }
  }, [])

  return {
    branches,
    activeBranchId,
    isLoading,
    isProcessing,
    loadBranches,
    createFork,
    switchBranch,
    updateStatus,
    reviveBranch,
    sendMessage,
  }
}
