import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { sessionsApi } from '@/api/sessions'
import { stepsApi } from '@/api/steps'
import { treesApi } from '@/api/trees'
import type { Tree, Session, DecisionRecord, TreeStructure, CustomStep, Step } from '@/types'
import type { CustomStepDraft } from '@/components/step-library/CustomStepModal'
import type { DescendantNode } from '@/components/session'

interface UseCustomStepFlowParams {
  tree: Tree | null
  session: Session | null
  currentNodeId: string
  pathTaken: string[]
  decisions: DecisionRecord[]
  notes: string
  findNode: (nodeId: string, structure?: TreeStructure) => TreeStructure | null
  setCurrentNodeId: (id: string) => void
  setPathTaken: (path: string[]) => void
  setDecisions: (decisions: DecisionRecord[]) => void
  setNotes: (notes: string) => void
  setError: (error: string | null) => void
  onEnterNode: (enteredAtIso: string) => void
  isCompleting: boolean
  onRequestCompletion: (completionDecision: DecisionRecord, source: 'custom') => void
}

export function useCustomStepFlow({
  tree,
  session,
  currentNodeId,
  pathTaken,
  decisions,
  notes,
  findNode,
  setCurrentNodeId,
  setPathTaken,
  setDecisions,
  setNotes,
  setError,
  onEnterNode,
  isCompleting,
  onRequestCompletion,
}: UseCustomStepFlowParams) {
  const navigate = useNavigate()

  // Custom steps
  const [customSteps, setCustomSteps] = useState<CustomStep[]>([])
  const [showCustomStepModal, setShowCustomStepModal] = useState(false)

  // Post-step action flow
  const [showPostStepModal, setShowPostStepModal] = useState(false)
  const [pendingStep, setPendingStep] = useState<Step | CustomStepDraft | null>(null)
  const [pendingStepIsFromLibrary, setPendingStepIsFromLibrary] = useState(false)
  const [isSavingStep, setIsSavingStep] = useState(false)

  // Continuation flow
  const [showContinuationModal, setShowContinuationModal] = useState(false)
  const [branchOriginNodeId, setBranchOriginNodeId] = useState<string | null>(null)
  const [pendingContinuationNodeId, setPendingContinuationNodeId] = useState<string | null>(null)

  // Custom branch mode
  const [customBranchMode, setCustomBranchMode] = useState(false)

  // Fork flow
  const [showForkModal, setShowForkModal] = useState(false)

  const findCustomStep = (nodeId: string): CustomStep | null => {
    return customSteps.find(cs => cs.id === nodeId) || null
  }

  // Get descendant nodes two levels deep (grandchildren) from a decision node's options.
  const getDescendantNodes = (decisionNodeId: string): DescendantNode[] => {
    const decisionNode = findNode(decisionNodeId, tree?.tree_structure)
    if (!decisionNode || decisionNode.type !== 'decision' || !decisionNode.options) {
      return []
    }

    const descendants: DescendantNode[] = []

    for (const option of decisionNode.options) {
      if (!option.next_node_id) continue
      const childNode = findNode(option.next_node_id, tree?.tree_structure)
      if (!childNode) continue

      if (childNode.type === 'decision' && childNode.options) {
        for (const childOption of childNode.options) {
          if (!childOption.next_node_id) continue
          const grandchild = findNode(childOption.next_node_id, tree?.tree_structure)
          if (!grandchild) continue

          descendants.push({
            id: grandchild.id,
            label: grandchild.question || grandchild.title || 'Untitled',
            type: grandchild.type,
            parentOptionLabel: `${option.label} \u2192 ${childOption.label}`
          })
        }
      } else if (childNode.type === 'action' && childNode.next_node_id) {
        const grandchild = findNode(childNode.next_node_id, tree?.tree_structure)
        if (grandchild) {
          descendants.push({
            id: grandchild.id,
            label: grandchild.question || grandchild.title || 'Untitled',
            type: grandchild.type,
            parentOptionLabel: `${option.label} \u2192 ${childNode.title || 'Action'}`
          })
        }
      }
    }

    return descendants
  }

  // Navigate back to a previously-created custom step from the decision node
  const handleNavigateToCustomStep = (customStep: CustomStep) => {
    const enteredAt = new Date().toISOString()
    const newPath = [...pathTaken, customStep.id]
    setPathTaken(newPath)
    setCurrentNodeId(customStep.id)
    onEnterNode(enteredAt)
  }

  // Called when CustomStepModal submits - show action modal instead of inserting directly
  const handleStepCreated = (step: Step | CustomStepDraft, isFromLibrary: boolean) => {
    setPendingStep(step)
    setPendingStepIsFromLibrary(isFromLibrary)
    setShowCustomStepModal(false)
    setShowPostStepModal(true)
  }

  const resetPendingStep = () => {
    setShowPostStepModal(false)
    setPendingStep(null)
    setPendingStepIsFromLibrary(false)
    setIsSavingStep(false)
  }

  // Save to library only, don't insert into session
  const handleSaveForLater = async () => {
    if (!pendingStep) return

    setIsSavingStep(true)
    try {
      if (!pendingStepIsFromLibrary) {
        await stepsApi.create({
          title: pendingStep.title,
          step_type: pendingStep.step_type,
          content: pendingStep.content,
          visibility: 'private',
          tags: pendingStep.tags || []
        })
      }
      resetPendingStep()
    } catch (err) {
      console.error('Failed to save step to library:', err)
      setIsSavingStep(false)
    }
  }

  // Insert into session and show continuation options
  const handleUseNow = async () => {
    if (!pendingStep || !session) return

    setIsSavingStep(true)
    try {
      setBranchOriginNodeId(currentNodeId)

      const customStep: CustomStep = {
        id: crypto.randomUUID(),
        inserted_after_node_id: currentNodeId,
        step_data: pendingStep,
        timestamp: new Date().toISOString()
      }

      const decisionTimestamp = new Date().toISOString()
      const newDecision: DecisionRecord = {
        node_id: customStep.id,
        question: null,
        answer: null,
        action_performed: `Custom Step: ${pendingStep.title}`,
        notes: pendingStep.content.instructions || null,
        automation_used: false,
        timestamp: decisionTimestamp,
        entered_at: decisionTimestamp,
        exited_at: decisionTimestamp,
        duration_seconds: 0,
        attachments: []
      }

      const newCustomSteps = [...customSteps, customStep]
      const newDecisions = [...decisions, newDecision]
      const newPath = [...pathTaken, customStep.id]

      setCustomSteps(newCustomSteps)
      setDecisions(newDecisions)
      setPathTaken(newPath)
      setCurrentNodeId(customStep.id)
      onEnterNode(decisionTimestamp)

      await sessionsApi.update(session.id, {
        path_taken: newPath,
        decisions: newDecisions,
        custom_steps: newCustomSteps
      })

      resetPendingStep()
      setShowContinuationModal(true)
    } catch (err) {
      console.error('Failed to insert custom step:', err)
      setIsSavingStep(false)
    }
  }

  // Save to library AND insert into session
  const handleBoth = async () => {
    if (!pendingStep) return

    setIsSavingStep(true)
    try {
      if (!pendingStepIsFromLibrary) {
        await stepsApi.create({
          title: pendingStep.title,
          step_type: pendingStep.step_type,
          content: pendingStep.content,
          visibility: 'private',
          tags: pendingStep.tags || []
        })
      }
      await handleUseNow()
    } catch (err) {
      console.error('Failed to save and insert step:', err)
      setIsSavingStep(false)
    }
  }

  // Handle selecting a descendant node from continuation modal
  const handleSelectDescendant = (nodeId: string) => {
    setShowContinuationModal(false)
    setBranchOriginNodeId(null)
    setPendingContinuationNodeId(nodeId)
  }

  // Navigate to the previously-selected descendant node
  const handleContinueToDescendant = async () => {
    if (!pendingContinuationNodeId || !session) return

    const enteredAt = new Date().toISOString()
    const newPath = [...pathTaken, pendingContinuationNodeId]
    setPathTaken(newPath)
    setCurrentNodeId(pendingContinuationNodeId)
    onEnterNode(enteredAt)
    setNotes('')
    setPendingContinuationNodeId(null)

    try {
      await sessionsApi.update(session.id, { path_taken: newPath })
    } catch (err) {
      console.error('Failed to update session path:', err)
    }
  }

  // Enter custom branch building mode
  const handleBuildCustomBranch = () => {
    setShowContinuationModal(false)
    setCustomBranchMode(true)
  }

  // Complete session from custom branch mode
  const handleCustomBranchComplete = async () => {
    if (!session) return

    setError(null)
    const completionDecision: DecisionRecord = {
      node_id: currentNodeId,
      question: null,
      answer: null,
      action_performed: 'Custom Branch Completed',
      notes: notes || 'Issue resolved via custom troubleshooting steps',
      automation_used: false,
      timestamp: new Date().toISOString(),
      attachments: []
    }
    onRequestCompletion(completionDecision, 'custom')
  }

  // Fork tree with custom branch
  const handleForkTree = async (name: string, description: string) => {
    if (!tree) return

    try {
      const forkedTree = await treesApi.create({
        name,
        description,
        tree_structure: tree.tree_structure,
        is_public: false
      })

      navigate(`/trees/${forkedTree.id}/edit`)
    } catch (err) {
      console.error('Failed to fork tree:', err)
      throw err
    }
  }

  // Skip forking and go to session detail
  const handleSkipFork = () => {
    setShowForkModal(false)
    navigate(`/sessions/${session!.id}`)
  }

  // Initialize custom steps when resuming a session
  const initCustomSteps = (steps: CustomStep[]) => {
    setCustomSteps(steps)
  }

  return {
    // State
    customSteps,
    showCustomStepModal,
    showPostStepModal,
    pendingStep,
    pendingStepIsFromLibrary,
    isSavingStep,
    showContinuationModal,
    branchOriginNodeId,
    pendingContinuationNodeId,
    customBranchMode,
    showForkModal,

    // Derived
    findCustomStep,
    getDescendantNodes,

    // Actions
    setShowCustomStepModal,
    setShowContinuationModal,
    setShowForkModal,
    initCustomSteps,
    handleNavigateToCustomStep,
    handleStepCreated,
    resetPendingStep,
    handleSaveForLater,
    handleUseNow,
    handleBoth,
    handleSelectDescendant,
    handleContinueToDescendant,
    handleBuildCustomBranch,
    handleCustomBranchComplete,
    handleForkTree,
    handleSkipFork,
    isCompleting,
  }
}
