import { createFileRoute, useNavigate, useParams } from '@tanstack/react-router'
import { Minus, Pencil, Plus, Sparkles } from 'lucide-react'
import { useEffect, useMemo, useRef, useState } from 'react'

import type { AsignaturaDetail } from '@/data'

import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Textarea } from '@/components/ui/textarea'
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from '@/components/ui/tooltip'
import { useSubject, useUpdateAsignatura } from '@/data/hooks/useSubjects'
import { columnParsers } from '@/lib/asignaturaColumnParsers'

export interface BibliografiaEntry {
  id: string
  tipo: 'BASICA' | 'COMPLEMENTARIA'
  cita: string
  fuenteBibliotecaId?: string
  fuenteBiblioteca?: any
}
export interface BibliografiaTabProps {
  id: string
  bibliografia: Array<BibliografiaEntry>
  onSave: (bibliografia: Array<BibliografiaEntry>) => void
  isSaving: boolean
}

export interface AsignaturaDatos {
  [key: string]: string
}

export interface AsignaturaResponse {
  datos: AsignaturaDatos
}

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value)
}

type CriterioEvaluacionRow = {
  criterio: string
  porcentaje: number
}

type CriterioEvaluacionRowDraft = {
  id: string
  criterio: string
  porcentaje: string // allow empty while editing
}

export const Route = createFileRoute(
  '/planes/$planId/asignaturas/$asignaturaId',
)({
  component: AsignaturaDetailPage,
})

export default function AsignaturaDetailPage() {
  const { asignaturaId } = useParams({
    from: '/planes/$planId/asignaturas/$asignaturaId',
  })
  const { data: asignaturaApi } = useSubject(asignaturaId)

  const [asignatura, setAsignatura] = useState<AsignaturaDetail | null>(null)
  const updateAsignatura = useUpdateAsignatura()

  const handlePersistDatoGeneral = (clave: string, value: string) => {
    const baseDatos = asignatura?.datos ?? (asignaturaApi as any)?.datos ?? {}
    const mergedDatos = { ...baseDatos, [clave]: value }

    // Mantener estado local coherente para merges posteriores.
    setAsignatura((prev) => ({
      ...((prev ?? asignaturaApi ?? {}) as any),
      datos: mergedDatos,
    }))

    updateAsignatura.mutate({
      asignaturaId,
      patch: {
        datos: mergedDatos,
      },
    })
  }
  /* ---------- sincronizar API ---------- */
  useEffect(() => {
    if (asignaturaApi) setAsignatura(asignaturaApi)
  }, [asignaturaApi])

  return <DatosGenerales onPersistDato={handlePersistDatoGeneral} />
}

function DatosGenerales({
  onPersistDato,
}: {
  onPersistDato: (clave: string, value: string) => void
}) {
  const { asignaturaId, planId } = useParams({
    from: '/planes/$planId/asignaturas/$asignaturaId',
  })
  const navigate = useNavigate()

  const { data: data, isLoading: isLoading } = useSubject(asignaturaId)
  const updateAsignatura = useUpdateAsignatura()

  const evaluationCardRef = useRef<HTMLDivElement | null>(null)
  const [evaluationForceEditToken, setEvaluationForceEditToken] =
    useState<number>(0)
  const [evaluationHighlightToken, setEvaluationHighlightToken] =
    useState<number>(0)

  // 1. Extraemos la definición de la estructura (los metadatos)
  const definicionRaw = data?.estructuras_asignatura?.definicion
  const definicion = isRecord(definicionRaw)
    ? (definicionRaw as Record<string, unknown>)
    : null

  const propertiesRaw = definicion ? (definicion as any).properties : undefined
  const structureProps = isRecord(propertiesRaw)
    ? (propertiesRaw as Record<string, any>)
    : {}

  // 2. Extraemos los valores reales (el contenido redactado)
  const datosRaw = data?.datos
  const valoresActuales = isRecord(datosRaw)
    ? (datosRaw as Record<string, any>)
    : {}

  const criteriosEvaluacion: Array<CriterioEvaluacionRow> = useMemo(() => {
    const raw = (data as any)?.criterios_de_evaluacion
    console.log(raw)

    if (!Array.isArray(raw)) return []

    const rows: Array<CriterioEvaluacionRow> = []
    for (const item of raw) {
      if (!isRecord(item)) continue
      const criterio = typeof item.criterio === 'string' ? item.criterio : ''
      const porcentajeNum =
        typeof item.porcentaje === 'number'
          ? item.porcentaje
          : typeof item.porcentaje === 'string'
            ? Number(item.porcentaje)
            : NaN

      if (!criterio.trim()) continue
      if (!Number.isFinite(porcentajeNum)) continue
      const porcentaje = Math.trunc(porcentajeNum)
      if (porcentaje < 1 || porcentaje > 100) continue

      rows.push({ criterio: criterio.trim(), porcentaje: porcentaje })
    }

    return rows
  }, [data])

  const openEvaluationEditor = () => {
    evaluationCardRef.current?.scrollIntoView({
      behavior: 'smooth',
      block: 'start',
    })

    const now = Date.now()
    setEvaluationForceEditToken(now)
    setEvaluationHighlightToken(now)
  }

  const persistCriteriosEvaluacion = async (
    rows: Array<CriterioEvaluacionRow>,
  ) => {
    await updateAsignatura.mutateAsync({
      asignaturaId: asignaturaId as any,
      patch: {
        criterios_de_evaluacion: rows,
      } as any,
    })
  }
  if (isLoading) return <p>Cargando información...</p>

  return (
    <div className="animate-in fade-in mx-auto max-w-7xl space-y-8 px-4 py-8 duration-500">
      {/* Encabezado de la Sección */}
      <div className="flex flex-col justify-between gap-4 border-b pb-6 md:flex-row md:items-center">
        <div>
          <h2 className="text-2xl font-bold tracking-tight text-slate-900">
            Datos Generales
          </h2>
          <p className="mt-1 text-slate-500">
            Información oficial estructurada bajo los lineamientos de la SEP.
          </p>
        </div>
      </div>

      {/* Grid de Información */}
      <div className="grid grid-cols-1 gap-6 md:grid-cols-3">
        {/* Columna Principal (Más ancha) */}
        <div className="space-y-6 md:col-span-2">
          {Object.entries(structureProps).map(
            ([key, config]: [string, any]) => {
              const cardTitle = config.title || key
              const description = config.description || ''

              const xColumn =
                typeof config?.['x-column'] === 'string'
                  ? config['x-column']
                  : undefined

              // Obtenemos el placeholder del arreglo 'examples' de la estructura
              const placeholder =
                config.examples && config.examples.length > 0
                  ? config.examples[0]
                  : ''

              const valActual = valoresActuales[key]

              let currentContent = valActual ?? ''

              if (xColumn) {
                const rawValue = (data as any)?.[xColumn]
                const parser = columnParsers[xColumn]
                currentContent = parser
                  ? parser(rawValue)
                  : String(rawValue ?? '')
              }

              return (
                <InfoCard
                  asignaturaId={asignaturaId}
                  key={key}
                  clave={key}
                  title={cardTitle}
                  initialContent={currentContent}
                  placeholder={placeholder}
                  description={description}
                  onPersist={({ clave, value }) =>
                    onPersistDato(String(clave ?? key), String(value ?? ''))
                  }
                  onClickEditButton={({ startEditing }) => {
                    switch (xColumn) {
                      case 'contenido_tematico': {
                        navigate({
                          to: '/planes/$planId/asignaturas/$asignaturaId/contenido',
                          params: { planId, asignaturaId },
                        })
                        return
                      }
                      case 'criterios_de_evaluacion': {
                        openEvaluationEditor()
                        return
                      }
                      default: {
                        startEditing()
                      }
                    }
                  }}
                />
              )
            },
          )}
        </div>

        {/* Columna Lateral (Información Secundaria) */}
        <div className="space-y-6">
          <div className="space-y-6">
            {/* Tarjeta de Requisitos */}
            <InfoCard
              title="Requisitos y Seriación"
              type="requirements"
              initialContent={[
                {
                  type: 'Pre-requisito',
                  code: 'PA-301',
                  name: 'Programación Avanzada',
                },
                {
                  type: 'Co-requisito',
                  code: 'MAT-201',
                  name: 'Matemáticas Discretas',
                },
              ]}
            />

            {/* Tarjeta de Evaluación */}
            <InfoCard
              title="Sistema de Evaluación"
              type="evaluation"
              initialContent={criteriosEvaluacion}
              containerRef={evaluationCardRef}
              forceEditToken={evaluationForceEditToken}
              highlightToken={evaluationHighlightToken}
              onPersist={({ value }) => persistCriteriosEvaluacion(value)}
            />
          </div>
        </div>
      </div>
    </div>
  )
}

interface InfoCardProps {
  asignaturaId?: string
  clave?: string
  title: string
  initialContent: any
  placeholder?: string
  description?: string
  required?: boolean // Nueva prop para el asterisco
  type?: 'text' | 'requirements' | 'evaluation'
  onEnhanceAI?: (content: any) => void
  onPersist?: (payload: {
    type: NonNullable<InfoCardProps['type']>
    clave?: string
    value: any
  }) => void | Promise<void>
  onClickEditButton?: (helpers: { startEditing: () => void }) => void

  containerRef?: React.RefObject<HTMLDivElement | null>
  forceEditToken?: number
  highlightToken?: number
}

function InfoCard({
  asignaturaId,
  clave,
  title,
  initialContent,
  placeholder,
  description,
  required,
  type = 'text',
  onPersist,
  onClickEditButton,
  containerRef,
  forceEditToken,
  highlightToken,
}: InfoCardProps) {
  const [isEditing, setIsEditing] = useState(false)
  const [isHighlighted, setIsHighlighted] = useState(false)
  const [data, setData] = useState(initialContent)
  const [tempText, setTempText] = useState(initialContent)

  const [evalRows, setEvalRows] = useState<Array<CriterioEvaluacionRowDraft>>(
    [],
  )
  const navigate = useNavigate()
  const { planId } = useParams({
    from: '/planes/$planId/asignaturas/$asignaturaId',
  })

  useEffect(() => {
    setData(initialContent)
    setTempText(initialContent)

    if (type === 'evaluation') {
      const raw = Array.isArray(initialContent) ? initialContent : []
      const rows: Array<CriterioEvaluacionRowDraft> = raw
        .map((r: any): CriterioEvaluacionRowDraft | null => {
          const criterio = typeof r?.criterio === 'string' ? r.criterio : ''
          const porcentajeNum =
            typeof r?.porcentaje === 'number'
              ? r.porcentaje
              : typeof r?.porcentaje === 'string'
                ? Number(r.porcentaje)
                : NaN

          const porcentaje = Number.isFinite(porcentajeNum)
            ? String(Math.trunc(porcentajeNum))
            : ''

          return {
            id: crypto.randomUUID(),
            criterio,
            porcentaje,
          }
        })
        .filter(Boolean) as Array<CriterioEvaluacionRowDraft>

      setEvalRows(rows)
    }
  }, [initialContent, type])

  useEffect(() => {
    if (!forceEditToken) return
    setIsEditing(true)
  }, [forceEditToken])

  useEffect(() => {
    if (!highlightToken) return
    setIsHighlighted(true)
    const t = window.setTimeout(() => setIsHighlighted(false), 900)
    return () => window.clearTimeout(t)
  }, [highlightToken])

  const handleSave = () => {
    console.log('clave, valor:', clave, String(tempText ?? ''))

    if (type === 'evaluation') {
      const cleaned: Array<CriterioEvaluacionRow> = []
      for (const r of evalRows) {
        const criterio = String(r.criterio).trim()
        const porcentajeStr = String(r.porcentaje).trim()
        if (!criterio) continue
        if (!porcentajeStr) continue

        const n = Number(porcentajeStr)
        if (!Number.isFinite(n)) continue
        const porcentaje = Math.trunc(n)
        if (porcentaje < 1 || porcentaje > 100) continue

        cleaned.push({ criterio, porcentaje })
      }

      setData(cleaned)
      setEvalRows(
        cleaned.map((x) => ({
          id: crypto.randomUUID(),
          criterio: x.criterio,
          porcentaje: String(x.porcentaje),
        })),
      )
      setIsEditing(false)

      void onPersist?.({ type, clave, value: cleaned })
      return
    }

    setData(tempText)
    setIsEditing(false)

    if (type === 'text') {
      void onPersist?.({ type, clave, value: String(tempText ?? '') })
    }
  }

  const handleIARequest = (campoClave: string) => {
    console.log(placeholder)

    // Añadimos un timestamp a la state para forzar que la navegación
    // genere una nueva ubicación incluso si la ruta y los params son iguales.
    navigate({
      to: '/planes/$planId/asignaturas/$asignaturaId/iaasignatura',
      params: { planId, asignaturaId: asignaturaId! },
      state: {
        activeTab: 'ia',
        prefillCampo: campoClave,
        prefillContenido: data,
        _ts: Date.now(),
      } as any,
    })
  }

  const evaluationTotal = useMemo(() => {
    if (type !== 'evaluation') return 0
    return evalRows.reduce((acc, r) => {
      const v = String(r.porcentaje).trim()
      if (!v) return acc
      const n = Number(v)
      if (!Number.isFinite(n)) return acc
      const porcentaje = Math.trunc(n)
      if (porcentaje < 1 || porcentaje > 100) return acc
      return acc + porcentaje
    }, 0)
  }, [type, evalRows])

  return (
    <div ref={containerRef as any}>
      <Card
        className={
          'overflow-hidden transition-all hover:border-slate-300 ' +
          (isHighlighted ? 'ring-primary/40 ring-2' : '')
        }
      >
        <TooltipProvider>
          <CardHeader className="border-b bg-slate-50/50 px-5 py-3">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-2">
                <Tooltip>
                  <TooltipTrigger asChild>
                    <CardTitle className="cursor-help text-sm font-bold text-slate-700">
                      {title}
                    </CardTitle>
                  </TooltipTrigger>
                  <TooltipContent side="top" className="max-w-xs text-xs">
                    {description || 'Información del campo'}
                  </TooltipContent>
                </Tooltip>

                {required && (
                  <span
                    className="text-sm font-bold text-red-500"
                    title="Requerido"
                  >
                    *
                  </span>
                )}
              </div>

              {!isEditing && (
                <div className="flex gap-1">
                  <Tooltip>
                    <TooltipTrigger asChild>
                      <Button
                        variant="ghost"
                        size="icon"
                        className="h-8 w-8 text-blue-500 hover:bg-blue-100"
                        onClick={() => clave && handleIARequest(clave)}
                      >
                        <Sparkles className="h-4 w-4" />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent>Mejorar con IA</TooltipContent>
                  </Tooltip>

                  <Tooltip>
                    <TooltipTrigger asChild>
                      <Button
                        variant="ghost"
                        size="icon"
                        className="h-8 w-8 text-slate-400"
                        onClick={() => {
                          const startEditing = () => setIsEditing(true)

                          if (onClickEditButton) {
                            onClickEditButton({ startEditing })
                            return
                          }

                          startEditing()
                        }}
                      >
                        <Pencil className="h-3 w-3" />
                      </Button>
                    </TooltipTrigger>
                    <TooltipContent>Editar campo</TooltipContent>
                  </Tooltip>
                </div>
              )}
            </div>
          </CardHeader>
        </TooltipProvider>

        <CardContent className="pt-4">
          {isEditing ? (
            <div className="space-y-3">
              {type === 'evaluation' ? (
                <div className="space-y-3">
                  <div className="space-y-2">
                    {evalRows.map((row) => (
                      <div
                        key={row.id}
                        className="grid grid-cols-[2fr_1fr_1ch_32px] items-center gap-2"
                      >
                        <Input
                          value={row.criterio}
                          placeholder="Criterio"
                          onChange={(e) => {
                            const nextCriterio = e.target.value
                            setEvalRows((prev) =>
                              prev.map((r) =>
                                r.id === row.id
                                  ? { ...r, criterio: nextCriterio }
                                  : r,
                              ),
                            )
                          }}
                        />

                        <Input
                          value={row.porcentaje}
                          placeholder="%"
                          type="number"
                          min={1}
                          max={100}
                          step={1}
                          inputMode="numeric"
                          onChange={(e) => {
                            const raw = e.target.value
                            // Solo permitir '' o dígitos
                            if (raw !== '' && !/^\d+$/.test(raw)) return

                            if (raw === '') {
                              setEvalRows((prev) =>
                                prev.map((r) =>
                                  r.id === row.id
                                    ? {
                                        id: r.id,
                                        criterio: r.criterio,
                                        porcentaje: '',
                                      }
                                    : r,
                                ),
                              )
                              return
                            }

                            const n = Number(raw)
                            if (!Number.isFinite(n)) return
                            const porcentaje = Math.trunc(n)
                            if (porcentaje < 1 || porcentaje > 100) return

                            // No permitir suma > 100
                            setEvalRows((prev) => {
                              const next = prev.map((r) =>
                                r.id === row.id
                                  ? {
                                      id: r.id,
                                      criterio: r.criterio,
                                      porcentaje: raw,
                                    }
                                  : r,
                              )

                              const total = next.reduce((acc, r) => {
                                const v = String(r.porcentaje).trim()
                                if (!v) return acc
                                const nn = Number(v)
                                if (!Number.isFinite(nn)) return acc
                                const vv = Math.trunc(nn)
                                if (vv < 1 || vv > 100) return acc
                                return acc + vv
                              }, 0)

                              return total > 100 ? prev : next
                            })
                          }}
                        />

                        <div
                          className="flex w-[1ch] items-center justify-center text-sm text-slate-600"
                          aria-hidden
                        >
                          %
                        </div>

                        <Button
                          variant="ghost"
                          size="icon"
                          className="h-8 w-8 text-red-600 hover:bg-red-50"
                          onClick={() => {
                            setEvalRows((prev) =>
                              prev.filter((r) => r.id !== row.id),
                            )
                          }}
                          aria-label="Quitar renglón"
                          title="Quitar"
                        >
                          <Minus className="h-4 w-4" />
                        </Button>
                      </div>
                    ))}
                  </div>

                  <div className="flex items-center justify-between">
                    <span
                      className={
                        'text-sm ' +
                        (evaluationTotal === 100
                          ? 'text-muted-foreground'
                          : 'text-destructive font-semibold')
                      }
                    >
                      Total: {evaluationTotal}/100
                    </span>

                    <Button
                      variant="ghost"
                      size="sm"
                      className="text-emerald-700 hover:bg-emerald-50"
                      onClick={() => {
                        // Agregar una fila vacía (siempre permitido)
                        setEvalRows((prev) => [
                          ...prev,
                          {
                            id: crypto.randomUUID(),
                            criterio: '',
                            porcentaje: '',
                          },
                        ])
                      }}
                    >
                      <Plus className="mr-2 h-4 w-4" /> Agregar renglón
                    </Button>
                  </div>
                </div>
              ) : (
                <Textarea
                  value={tempText}
                  placeholder={placeholder}
                  onChange={(e) => setTempText(e.target.value)}
                  className="min-h-30 text-sm leading-relaxed"
                />
              )}
              <div className="flex justify-end gap-2">
                <Button
                  size="sm"
                  variant="ghost"
                  onClick={() => {
                    setIsEditing(false)
                    if (type === 'evaluation') {
                      const raw = Array.isArray(data) ? data : []
                      setEvalRows(
                        raw.map((r: CriterioEvaluacionRow) => ({
                          id: crypto.randomUUID(),
                          criterio:
                            typeof r.criterio === 'string' ? r.criterio : '',
                          porcentaje:
                            typeof r.porcentaje === 'number'
                              ? String(Math.trunc(r.porcentaje))
                              : typeof r.porcentaje === 'string'
                                ? String(Math.trunc(Number(r.porcentaje)))
                                : '',
                        })),
                      )
                    }
                  }}
                >
                  Cancelar
                </Button>
                <Button
                  size="sm"
                  className="bg-[#00a878] hover:bg-[#008f66]"
                  onClick={handleSave}
                  disabled={type === 'evaluation' && evaluationTotal > 100}
                >
                  Guardar
                </Button>
              </div>
            </div>
          ) : (
            <div className="text-sm leading-relaxed text-slate-600">
              {type === 'text' &&
                (data ? (
                  <p className="whitespace-pre-wrap">{data}</p>
                ) : (
                  <p className="text-slate-400 italic">Sin información.</p>
                ))}
              {type === 'requirements' && <RequirementsView items={data} />}
              {type === 'evaluation' && (
                <EvaluationView items={data as Array<CriterioEvaluacionRow>} />
              )}
            </div>
          )}
        </CardContent>
      </Card>
    </div>
  )
}

// Vista de Requisitos
function RequirementsView({ items }: { items: Array<any> }) {
  return (
    <div className="space-y-3">
      {items.map((req, i) => (
        <div
          key={i}
          className="rounded-lg border border-slate-100 bg-slate-50 p-3"
        >
          <p className="text-[10px] font-bold tracking-tight text-slate-400 uppercase">
            {req.type}
          </p>
          <p className="text-sm font-medium text-slate-700">
            {req.code} {req.name}
          </p>
        </div>
      ))}
    </div>
  )
}

// Vista de Evaluación
function EvaluationView({ items }: { items: Array<CriterioEvaluacionRow> }) {
  const porcentajeTotal = items.reduce(
    (total, item) => total + Number(item.porcentaje),
    0,
  )
  return (
    <div className="space-y-2">
      {items.map((item, i) => (
        <div
          key={i}
          className="flex justify-between border-b border-slate-50 pb-1.5 text-sm italic"
        >
          <span className="text-slate-500">{item.criterio}</span>
          <span className="font-bold text-blue-600">{item.porcentaje}%</span>
        </div>
      ))}
      {porcentajeTotal < 100 && (
        <p className="text-destructive text-sm font-medium">
          El porcentaje total es menor a 100%.
        </p>
      )}
    </div>
  )
}
