import { useEffect, useState, useCallback } from 'react'
import { useParams, useNavigate, useSearchParams } from 'react-router-dom'
import { Save, ArrowLeft, ListOrdered, Wrench, Settings, FileText, Calendar, Sparkles, Layers } from 'lucide-react'
import { analytics } from '@/lib/analytics'
import { Button } from '@/components/ui/Button'
import { treesApi } from '@/api/trees'
import { useProceduralEditorStore } from '@/store/proceduralEditorStore'
import { CollapsibleEditorSection } from '@/components/procedural-editor/CollapsibleEditorSection'
import { IntakeFormBuilder } from '@/components/procedural-editor/IntakeFormBuilder'
import { MaintenanceScheduleSection } from '@/components/procedural-editor/MaintenanceScheduleSection'
import { getScheduleSummary } from '@/components/procedural-editor/scheduleUtils'
import { StepList } from '@/components/procedural-editor/StepList'
import { TagInput } from '@/components/common/TagInput'
import { Spinner } from '@/components/common/Spinner'
import { EditorAIPanel } from '@/components/editor-ai/EditorAIPanel'
import { ContextMenu } from '@/components/common/ContextMenu'
import { ValidationSummary } from '@/components/tree-editor/ValidationSummary'
import { AIFixReviewModal } from '@/components/tree-editor/AIFixReviewModal'
import { useEditorAI } from '@/hooks/useEditorAI'
import { cn } from '@/lib/utils'
import { toast } from '@/lib/toast'
import type { TreeType, MaintenanceSchedule, TargetList, ProceduralStep, IntakeFormField, AIFixProposal } from '@/types'
import type { ValidationError } from '@/store/treeEditorStore'

type SectionKey = 'details' | 'intake' | 'schedule'

export function ProceduralEditorPage() {
  const { id } = useParams<{ id: string }>()
  const [searchParams] = useSearchParams()
  const navigate = useNavigate()
  const isEditMode = !!id

  const {
    treeId,
    treeType,
    name,
    description,
    tags,
    isPublic,
    intakeForm,
    isDirty,
    isSaving,
    isLoading,
    initNew,
    loadTree,
    reset,
    setName,
    setDescription,
    setTags,
    setIsPublic,
    setIsSaving,
    markSaved,
    getTreeForSave,
    replaceSteps,
  } = useProceduralEditorStore()

  const steps = useProceduralEditorStore(s => s.steps)
  const validationErrors = useProceduralEditorStore((s) => s.validationErrors)
  const setExpandedStepId = useProceduralEditorStore((s) => s.setExpandedStepId)
  const updateStep = useProceduralEditorStore((s) => s.updateStep)

  const handleFlowUpdate = useCallback((workingTree: Record<string, unknown>, metadata?: Record<string, unknown> | null) => {
    const stepsData = workingTree.steps as ProceduralStep[] | undefined
    if (stepsData && Array.isArray(stepsData)) {
      // Intake form may be in working_tree or in metadata
      const intakeData = (workingTree.intake_form || metadata?.intake_form) as IntakeFormField[] | undefined
      replaceSteps(stepsData, intakeData)
    }
  }, [replaceSteps])

  const editorAI = useEditorAI({
    flowType: 'procedural',
    treeId: id,
    getFlowContext: useCallback(() => {
      return {
        name,
        description,
        steps: steps as unknown as Record<string, unknown>[],
        intake_form: intakeForm,
      }
    }, [steps, intakeForm, name, description]),
    onFlowUpdate: handleFlowUpdate,
  })

  const [isFixing, setIsFixing] = useState(false)
  const [fixProposals, setFixProposals] = useState<AIFixProposal[] | null>(null)

  const isMaintenance = treeType === 'maintenance'
  const flowLabel = isMaintenance ? 'Maintenance Flow' : 'Procedure'

  // Accordion state: only one section open at a time
  const [expandedSection, setExpandedSection] = useState<SectionKey | null>(
    isEditMode ? null : 'details'
  )

  // Schedule state for collapsed summary
  const [schedule, setSchedule] = useState<MaintenanceSchedule | null>(null)
  const [scheduleTargetList, setScheduleTargetList] = useState<TargetList | null>(null)

  const toggleSection = useCallback((key: SectionKey) => {
    setExpandedSection(prev => prev === key ? null : key)
  }, [])

  const handleScheduleLoaded = useCallback((s: MaintenanceSchedule | null, tl: TargetList | null) => {
    setSchedule(s)
    setScheduleTargetList(tl)
  }, [])

  // Load tree or init new
  useEffect(() => {
    if (isEditMode && id) {
      loadExistingTree(id)
    } else {
      const urlType = searchParams.get('type')
      initNew((urlType === 'maintenance' ? 'maintenance' : 'procedural') as TreeType)
      // New flows: details expanded, or schedule for new maintenance
      setExpandedSection(urlType === 'maintenance' ? 'schedule' : 'details')
    }

    return () => { reset() }
  }, [id])

  useEffect(() => {
    useProceduralEditorStore.getState().validate()
  }, [steps, intakeForm])

  const loadExistingTree = async (treeId: string) => {
    try {
      const tree = await treesApi.get(treeId)
      if (tree.tree_type !== 'procedural' && tree.tree_type !== 'maintenance') {
        toast.error('This flow is not a procedural or maintenance flow')
        navigate('/trees')
        return
      }
      loadTree(tree)
    } catch {
      toast.error('Failed to load flow')
      navigate('/trees')
    }
  }

  const handleSelectStep = useCallback((stepId: string) => {
    // Guard against setExpandedStepId's toggle behavior — calling it with the same ID collapses the step
    const currentExpanded = useProceduralEditorStore.getState().expandedStepId
    if (currentExpanded !== stepId) {
      setExpandedStepId(stepId)
    }
    // Small delay to let expanded state render before scrolling
    setTimeout(() => {
      const el = document.querySelector(`[data-step-id="${stepId}"]`)
      if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' })
    }, 50)
  }, [setExpandedStepId])

  const handleFixWithAI = async () => {
    const fixableErrors = validationErrors
      .filter((e) => e.severity === 'error' && e.stepId)
      .map((e) => ({ node_id: e.stepId!, message: e.message }))

    if (fixableErrors.length === 0) return

    setIsFixing(true)
    try {
      const result = await treesApi.fixTree({
        tree_structure: { steps } as unknown as Record<string, unknown>,
        tree_name: name,
        tree_type: treeType as 'procedural' | 'maintenance',
        validation_errors: fixableErrors,
      })
      if (result.fixes.length > 0) {
        setFixProposals(result.fixes)
      } else {
        toast.info('AI could not generate fixes for these errors')
      }
    } catch {
      toast.error('Failed to generate AI fixes. Please try again.')
    } finally {
      setIsFixing(false)
    }
  }

  const handleApplyFix = (fix: AIFixProposal) => {
    updateStep(fix.target_node_id, fix.fixed_node as Partial<ProceduralStep>)
    useProceduralEditorStore.getState().validate()
  }

  // AIFixReviewModal.onApplyAll is () => void — no arguments
  const handleApplyAllFixes = () => {
    if (!fixProposals) return
    fixProposals.forEach((fix) => {
      updateStep(fix.target_node_id, fix.fixed_node as Partial<ProceduralStep>)
    })
    useProceduralEditorStore.getState().validate()
    setFixProposals(null)
  }

  const handleCloseFixModal = () => setFixProposals(null)

  const handleSave = async (saveStatus?: 'draft' | 'published') => {
    if (!name.trim()) {
      toast.error(`Please enter a name for the ${flowLabel.toLowerCase()}`)
      return
    }

    // Block publish if there are validation errors
    const errors = useProceduralEditorStore.getState().validate()
    const hasErrors = errors.some((e) => e.severity === 'error')
    if (hasErrors && saveStatus === 'published') {
      toast.error('Please fix all errors before publishing')
      return
    }

    setIsSaving(true)
    try {
      const payload = getTreeForSave()
      if (saveStatus) {
        payload.status = saveStatus
      }

      if (isEditMode && treeId) {
        await treesApi.update(treeId, payload)
        markSaved()
        toast.success(`${flowLabel} saved`)
      } else {
        const created = await treesApi.create(payload)
        analytics.flowCreated({ flow_type: payload.tree_type || 'procedural', method: 'manual' })
        markSaved()
        toast.success(`${flowLabel} created`)
        navigate(`/flows/${created.id}/edit`, { replace: true })
      }
    } catch (err: unknown) {
      const message = err && typeof err === 'object' && 'response' in err
        ? (err as { response?: { data?: { detail?: string | { message?: string } } } }).response?.data?.detail
        : null
      const errorText = typeof message === 'string' ? message : typeof message === 'object' && message?.message ? message.message : `Failed to save ${flowLabel.toLowerCase()}`
      toast.error(errorText)
    } finally {
      setIsSaving(false)
    }
  }

  // Summary strings for collapsed sections
  const detailsSummary = [
    tags.length > 0 ? `${tags.length} tag${tags.length !== 1 ? 's' : ''}` : 'No tags',
    isPublic ? 'Public' : 'Private',
    description ? `${description.slice(0, 40)}${description.length > 40 ? '\u2026' : ''}` : 'No description',
  ].join(' \u00b7 ')

  const scheduleSummary = getScheduleSummary(schedule, scheduleTargetList)

  const intakeSummary = intakeForm.length === 0
    ? 'No fields defined'
    : `${intakeForm.length} field${intakeForm.length !== 1 ? 's' : ''}: ${intakeForm.map(f => f.label || f.variable_name).slice(0, 4).join(', ')}${intakeForm.length > 4 ? ', \u2026' : ''}`

  if (isLoading) {
    return (
      <div className="flex min-h-[50vh] items-center justify-center">
        <Spinner />
      </div>
    )
  }

  return (
    <div className="flex h-full overflow-hidden">
      {/* Main content column */}
      <div className="flex min-w-0 flex-1 flex-col overflow-hidden">
      {/* Toolbar — sticky */}
      <div className="flex shrink-0 items-center gap-3 border-b border-border bg-sidebar px-4 py-2.5">
        <button
          onClick={() => navigate('/trees')}
          className="shrink-0 rounded p-1.5 text-muted-foreground transition-colors hover:bg-white/[0.08] hover:text-foreground"
        >
          <ArrowLeft className="h-4 w-4" />
        </button>

        <div className="flex min-w-0 flex-1 items-center gap-2">
          {isMaintenance
            ? <Wrench className="h-4 w-4 shrink-0 text-amber-400" />
            : <ListOrdered className="h-4 w-4 shrink-0 text-muted-foreground" />}
          <input
            type="text"
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder={`Untitled ${flowLabel}`}
            className="min-w-0 flex-1 bg-transparent text-sm font-semibold text-heading placeholder:text-muted-foreground focus:outline-none"
          />
          {isDirty && (
            <span
              title="Unsaved changes"
              className="h-1.5 w-1.5 shrink-0 rounded-full bg-amber-400"
            />
          )}
        </div>

        <div className="flex shrink-0 items-center gap-2">
          <button
            onClick={() => editorAI.isOpen ? editorAI.closePanel() : editorAI.openPanel()}
            title="Toggle AI Assist panel"
            className={cn(
              'flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-sm font-medium transition-colors',
              editorAI.isOpen
                ? 'border-primary/30 bg-accent-dim text-primary'
                : 'text-muted-foreground hover:bg-white/[0.08] hover:text-foreground'
            )}
          >
            <Sparkles className="h-4 w-4" />
            AI Assist
          </button>
          <Button
            variant="secondary"
            onClick={() => handleSave('draft')}
            disabled={isSaving}
          >
            Save Draft
          </Button>
          <Button
            onClick={() => handleSave('published')}
            loading={isSaving}
          >
            <Save className="h-4 w-4" />
            {isSaving ? 'Saving...' : 'Publish'}
          </Button>
        </div>
      </div>

      {/* Config zone */}
      <div className="shrink-0 border-b border-border bg-card">
        <CollapsibleEditorSection
          title="Details"
          icon={<Settings className="h-4 w-4" />}
          summary={detailsSummary}
          expanded={expandedSection === 'details'}
          onToggle={() => toggleSection('details')}
        >
          <div className="space-y-4">
            <div>
              <label className="mb-1 block text-sm font-medium text-muted-foreground">Description</label>
              <textarea
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder="Brief description of this procedure..."
                rows={2}
                className="w-full rounded-lg border border-border bg-card px-3 py-2 text-foreground placeholder:text-muted-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20"
              />
            </div>

            <div className="grid grid-cols-2 gap-4">
              <div>
                <label className="mb-1 block text-sm font-medium text-muted-foreground">Tags</label>
                <TagInput tags={tags} onChange={setTags} />
              </div>

              <div className="flex items-end pb-1">
                <label className="flex items-center gap-2 text-sm text-muted-foreground">
                  <input
                    type="checkbox"
                    checked={isPublic}
                    onChange={(e) => setIsPublic(e.target.checked)}
                    className="rounded border-border"
                  />
                  Public (visible to all users)
                </label>
              </div>
            </div>
          </div>
        </CollapsibleEditorSection>

        <CollapsibleEditorSection
          title="Intake Form"
          icon={<FileText className="h-4 w-4" />}
          summary={intakeSummary}
          expanded={expandedSection === 'intake'}
          onToggle={() => toggleSection('intake')}
        >
          <IntakeFormBuilder />
        </CollapsibleEditorSection>

        {isMaintenance && (
          <CollapsibleEditorSection
            title="Schedule"
            icon={<Calendar className="h-4 w-4" />}
            summary={scheduleSummary}
            expanded={expandedSection === 'schedule'}
            onToggle={() => toggleSection('schedule')}
          >
            <MaintenanceScheduleSection
              treeId={treeId}
              onScheduleLoaded={handleScheduleLoaded}
            />
          </CollapsibleEditorSection>
        )}
      </div>

      {/* Step canvas */}
      <div className="min-h-0 flex-1 overflow-y-auto bg-page">
        <div className="px-5 py-5">
          {validationErrors.length > 0 && (
            <div className="mb-4">
              <ValidationSummary
                errors={validationErrors.map((e): ValidationError => ({
                  nodeId: e.stepId,
                  field: e.field,
                  message: e.message,
                  severity: e.severity,
                }))}
                onSelectNode={handleSelectStep}
                onFixWithAI={handleFixWithAI}
                isFixing={isFixing}
                itemLabel="step"
              />
            </div>
          )}
          <StepList onStepContextMenu={editorAI.openContextMenu} />
        </div>
      </div>

      {editorAI.contextMenu && (
        <ContextMenu
          position={editorAI.contextMenu.position}
          items={[
            {
              id: 'generate-steps',
              label: 'Generate Steps After',
              icon: <Sparkles className="h-4 w-4" />,
              onClick: () => editorAI.triggerAction(
                editorAI.contextMenu!.nodeId,
                'add_steps',
                `Generate steps after this step`
              ),
            },
            {
              id: 'expand-step',
              label: 'Expand Step',
              icon: <Layers className="h-4 w-4" />,
              onClick: () => editorAI.triggerAction(
                editorAI.contextMenu!.nodeId,
                'quick_action',
                `Expand this step into detailed substeps`
              ),
            },
          ]}
          onClose={editorAI.closeContextMenu}
        />
      )}
      </div>{/* end main content column */}

      <EditorAIPanel
        isOpen={editorAI.isOpen}
        onClose={editorAI.closePanel}
        focalNode={null}
        flowName={name}
        flowType={isMaintenance ? 'maintenance' : 'procedural'}
        nodeCount={steps.length}
        messages={editorAI.messages}
        input={editorAI.input}
        onInputChange={editorAI.setInput}
        onSend={editorAI.sendMessage}
        isLoading={editorAI.isLoading}
        suggestions={editorAI.suggestions}
      />

      {fixProposals && (
        <AIFixReviewModal
          fixes={fixProposals}
          onApply={handleApplyFix}
          onApplyAll={handleApplyAllFixes}
          onClose={handleCloseFixModal}
        />
      )}
    </div>
  )
}

export default ProceduralEditorPage
