import { useEffect, useRef, useState } from 'react'
import { Box, Tab, Tabs, Typography } from '@mui/material'
import { useLocation, useNavigate } from 'react-router'
import { useQueryClient } from '@tanstack/react-query'
import {
  NeedBuilderProgress,
  NeedInput,
  VoiceNeedInput,
  WeightingEditor,
  NeedBuilderErrorState,
} from '../../components/demand'
import { AISearchActionBar } from '../../components/demand/AISearchActionBar'
import { AISearchSavePreview } from '../../components/demand/AISearchSavePreview'
import { SavedProfilesTab } from '../../components/demand/SavedProfilesTab'
import { AddToPipelineDialog } from '../../components/shortlist'
import { InquiryQuickDialog } from '../../components/match-detail/InquiryQuickDialog'
import { useParseNeed } from '../../hooks/useAI'
import { useCreateNeed, useNeed, useNeedProfiles } from '../../hooks/useNeeds'
import { useDefaultWeights } from '../../hooks/useWeighting'
import { NeedBuilderStep } from '../../domain/needBuilder'
import type { ParseNeedResult, ParsedNeedCriteria, WeightingKey } from '../../domain/needBuilder'
import { generateSummary, buildNeedInput, needToParsedCriteria } from '../../services/aiSearch/needSearchMapper'

type ActionIntent = 'search' | 'save-profile'

export default function AISearch() {
  const navigate = useNavigate()
  const queryClient = useQueryClient()

  const parseNeedMutation = useParseNeed()
  const createNeedMutation = useCreateNeed()
  const defaultWeights = useDefaultWeights()

  const [step, setStep] = useState<typeof NeedBuilderStep[keyof typeof NeedBuilderStep]>(NeedBuilderStep.IDLE)
  const [intent, setIntent] = useState<ActionIntent>('search')
  const [inputText, setInputText] = useState('')
  const [isAutoGen, setIsAutoGen] = useState(false)
  const [criteria, setCriteria] = useState<ParsedNeedCriteria>({})
  const [parseResult, setParseResult] = useState<ParseNeedResult | null>(null)
  const [editedCriteria, setEditedCriteria] = useState<ParsedNeedCriteria | null>(null)
  const [weights, setWeights] = useState<Record<WeightingKey, number>>(defaultWeights)
  const [weightingKey, setWeightingKey] = useState(0)
  const [needTitle, setNeedTitle] = useState('')
  const [isAnonymous, setIsAnonymous] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const [tab, setTab] = useState(0)
  const { data: savedProfiles = [] } = useNeedProfiles()

  const locationPrefillId = (useLocation().state as { prefillNeedId?: string } | null)?.prefillNeedId
  const [internalPrefillId, setInternalPrefillId] = useState<string | undefined>()
  const prefillNeedId = internalPrefillId ?? locationPrefillId
  const { data: prefillNeed } = useNeed(prefillNeedId ?? '')

  const isManualTextRef = useRef(false)

  useEffect(() => {
    if (!prefillNeed) return
    setCriteria(needToParsedCriteria(prefillNeed))
    setWeights(prefillNeed.weightingProfile as Record<WeightingKey, number>)
    setNeedTitle(prefillNeed.companyName)
    setWeightingKey(k => k + 1)
    setTab(0)
  }, [prefillNeed])

  function handleCriteriaChange(next: ParsedNeedCriteria) {
    setCriteria(next)
    if (!isManualTextRef.current) {
      const summary = generateSummary(next)
      setInputText(summary)
      setIsAutoGen(!!summary)
    }
  }

  function handleTextChange(text: string) {
    isManualTextRef.current = text !== ''
    setIsAutoGen(false)
    setInputText(text)
    setCriteria({})
    setParseResult(null)
  }

  function handleAiAutofill() {
    setStep(NeedBuilderStep.PARSING)
    setError(null)
    parseNeedMutation.mutate(inputText, {
      onSuccess: (resp) => {
        const result = resp.data
        setParseResult(result)
        setCriteria({ ...result.extractedCriteria })
        setWeights(result.suggestedWeights as Record<WeightingKey, number>)
        setWeightingKey(k => k + 1)
        isManualTextRef.current = false
        setInputText('')
        setIsAutoGen(false)
        setStep(NeedBuilderStep.IDLE)
      },
      onError: () => {
        setError('Die KI-Analyse ist fehlgeschlagen.')
        setStep(NeedBuilderStep.ERROR)
      },
    })
  }

  function handleAction(chosenIntent: ActionIntent) {
    setIntent(chosenIntent)
    setError(null)

    const resolved: ParsedNeedCriteria = criteria
    const resolvedResult: ParseNeedResult | null = parseResult

    if (!hasStructuredData && inputText.trim()) {
      setStep(NeedBuilderStep.PARSING)
      parseNeedMutation.mutate(inputText, {
        onSuccess: (resp) => {
          const parsedResolved = resp.data.extractedCriteria
          const parsedResult = resp.data
          setCriteria(parsedResolved)
          setWeights(resp.data.suggestedWeights as Record<WeightingKey, number>)
          setWeightingKey(k => k + 1)
          isManualTextRef.current = false
          setInputText('')
          setIsAutoGen(false)
          setParseResult(resp.data)
          continueAction(chosenIntent, parsedResolved, parsedResult)
        },
        onError: () => {
          setError('Die KI-Analyse ist fehlgeschlagen.')
          setStep(NeedBuilderStep.ERROR)
        },
      })
      return
    }

    continueAction(chosenIntent, resolved, resolvedResult)
  }

  function continueAction(
    chosenIntent: ActionIntent,
    resolved: ParsedNeedCriteria,
    resolvedResult: ParseNeedResult | null,
  ) {
    if (chosenIntent === 'search') {
      setStep(NeedBuilderStep.SAVING)
      const conf = resolvedResult
        ? Object.values(resolvedResult.confidenceByField).reduce((s, v) => s + v, 0) /
          Math.max(Object.values(resolvedResult.confidenceByField).length, 1)
        : 0.5
      const input = buildNeedInput(resolved, weights, needTitle, conf, 'DRAFT')
      createNeedMutation.mutate(input, {
        onSuccess: (created) => {
          queryClient.invalidateQueries({ queryKey: ['matches'] })
          navigate('/demand/results', { state: { fromNeedBuilder: true, activeNeedId: created.data.id } })
        },
        onError: () => {
          setError('Suche fehlgeschlagen.')
          setStep(NeedBuilderStep.ERROR)
        },
      })
      return
    }

    const confidenceByField: Record<string, number> = resolvedResult?.confidenceByField ?? {}
    if (!resolvedResult) {
      if (resolved.assetType) confidenceByField.assetType = 1.0
      if (resolved.areaRange?.min) confidenceByField.areaRange = 1.0
      if (resolved.preferredLocations?.length) confidenceByField.preferredLocations = 1.0
      if (resolved.budgetRange?.maxPerSqm) confidenceByField.budgetRange = 1.0
      if (resolved.timing?.earliestMoveIn) confidenceByField.timing = 1.0
    }
    setEditedCriteria({ ...resolved })
    setParseResult(resolvedResult ?? {
      extractedCriteria: resolved,
      confidenceByField,
      missingFields: [],
      assumptions: [],
      suggestedWeights: weights,
      followUpQuestionCandidates: [],
      rawSummary: 'Manuell eingegeben',
      promptVersion: 'manual',
      schemaVersion: '1.0',
    })
    setStep(NeedBuilderStep.READY_TO_SAVE)
  }

  function handleSaveProfile() {
    if (!editedCriteria || !parseResult) return
    setStep(NeedBuilderStep.SAVING)
    const entries = Object.entries(parseResult.confidenceByField)
    const conf = entries.length > 0 ? entries.reduce((s, [, v]) => s + v, 0) / entries.length : 0
    const input = buildNeedInput({ ...editedCriteria, isAnonymous: isAnonymous || undefined }, weights, needTitle, conf, 'ACTIVE')
    createNeedMutation.mutate(input, {
      onSuccess: (created) => {
        queryClient.invalidateQueries({ queryKey: ['matches'] })
        navigate('/demand/results', { state: { fromNeedBuilder: true, activeNeedId: created.data.id } })
      },
      onError: () => {
        setError('Speichern fehlgeschlagen.')
        setStep(NeedBuilderStep.ERROR)
      },
    })
  }

  function handleRetry() {
    setStep(NeedBuilderStep.IDLE)
    setError(null)
    setParseResult(null)
    setEditedCriteria(null)
  }

  const hasStructuredData = !!(
    criteria.assetType ||
    (criteria.areaRange?.min ?? 0) > 0 ||
    (criteria.preferredLocations?.length ?? 0) > 0
  )
  const canProceed = hasStructuredData || inputText.trim().length > 0
  const isProcessing = step === NeedBuilderStep.PARSING || step === NeedBuilderStep.SAVING
  const isSaveStep = step === NeedBuilderStep.READY_TO_SAVE || step === NeedBuilderStep.SAVING

  const vals = parseResult ? Object.values(parseResult.confidenceByField) : []
  const overallConfidence = vals.length > 0 ? vals.reduce((s, v) => s + v, 0) / vals.length : 0

  const savedCount = savedProfiles.filter(n => !n.status || n.status === 'ACTIVE' || n.status === 'DRAFT').length

  return (
    <Box sx={{ display: 'flex', flexDirection: 'column', height: '100%', overflow: 'hidden' }}>
      <AddToPipelineDialog />
      <InquiryQuickDialog />
      <Box sx={{ bgcolor: 'white', borderBottom: '1px solid #e8e7e4', px: 3, py: 2.5, flexShrink: 0 }}>
        <Typography sx={{ fontWeight: 700, fontSize: '1.125rem', lineHeight: 1.3, color: '#0f172a' }}>Flächensuche</Typography>
        <Typography variant="body2" color="text.secondary">
          Sprechen, schreiben oder Felder ausfüllen — dann sofort suchen oder als Suchprofil speichern
        </Typography>
      </Box>

      <Tabs
        value={tab}
        onChange={(_, v: number) => setTab(v)}
        sx={{ borderBottom: '1px solid #e2e8f0', px: 3, bgcolor: 'white', flexShrink: 0, minHeight: 44 }}
      >
        <Tab label="Neue Suche" sx={{ textTransform: 'none', fontWeight: 600, fontSize: '0.875rem', minHeight: 44, py: 0 }} />
        <Tab label={`Gespeicherte Profile (${savedCount})`} sx={{ textTransform: 'none', fontWeight: 600, fontSize: '0.875rem', minHeight: 44, py: 0 }} />
      </Tabs>

      {tab === 0 && (
        <>
          <NeedBuilderProgress step={step} />
          <Box sx={{ flex: 1, overflowY: 'auto', px: 3, py: 3 }}>

            {(step === NeedBuilderStep.IDLE || step === NeedBuilderStep.PARSING) && (
              <Box sx={{ display: 'flex', flexDirection: 'column', gap: 3, maxWidth: { md: 900, xl: 1200 }, mx: 'auto' }}>
                <VoiceNeedInput
                  text={inputText}
                  onTextChange={handleTextChange}
                  isAutoGen={isAutoGen}
                  onAiSubmit={handleAiAutofill}
                  isAnalyzing={step === NeedBuilderStep.PARSING}
                />
                <Box className="grid grid-cols-2 gap-4" sx={{ alignItems: 'start' }}>
                  <NeedInput criteria={criteria} onCriteriaChange={handleCriteriaChange} />
                  <WeightingEditor
                    key={weightingKey}
                    weights={weights}
                    onChange={setWeights}
                    assetType={criteria.assetType}
                  />
                </Box>
                <AISearchActionBar
                  canProceed={canProceed}
                  isSearching={isProcessing && intent === 'search'}
                  isSavingProfile={isProcessing && intent === 'save-profile'}
                  onSearch={() => handleAction('search')}
                  onSaveProfile={() => handleAction('save-profile')}
                />
              </Box>
            )}

            {isSaveStep && parseResult && editedCriteria && (
              <AISearchSavePreview
                criteria={editedCriteria}
                weights={weights}
                parseResult={parseResult}
                needTitle={needTitle}
                overallConfidence={overallConfidence}
                isSaving={step === NeedBuilderStep.SAVING}
                isAnonymous={isAnonymous}
                onNeedTitleChange={setNeedTitle}
                onAnonymousChange={setIsAnonymous}
                onBack={() => setStep(NeedBuilderStep.IDLE)}
                onSave={handleSaveProfile}
              />
            )}

            {step === NeedBuilderStep.ERROR && (
              <NeedBuilderErrorState message={error ?? 'Unbekannter Fehler'} onRetry={handleRetry} />
            )}
          </Box>
        </>
      )}

      {tab === 1 && (
        <Box sx={{ flex: 1, overflow: 'hidden' }}>
          <SavedProfilesTab onNewSearch={(id) => { setInternalPrefillId(id); setTab(0) }} />
        </Box>
      )}
    </Box>
  )
}
