'use client'

// React Imports
import type { RefObject } from 'react'
import { useEffect, useMemo, useState, useCallback, useContext } from 'react'
import { useTranslations } from 'next-intl'

// Context Imports
import NavbarSlotContext from '@/contexts/navbarSlotContext'

// MUI Imports
import Grid from '@mui/material/Grid2'
import IconButton from '@mui/material/IconButton'
import Box from '@mui/material/Box'
import CircularProgress from '@mui/material/CircularProgress'

// Third-party imports
import { useDragAndDrop } from '@formkit/drag-and-drop/react'
import { animations } from '@formkit/drag-and-drop'

// Component Imports
import FarmOverviewKPIs from '@views/dashboards/farm/FarmOverviewKPIs'
import FarmWeatherCard from '@views/dashboards/farm/FarmWeatherCard'
import FarmAlertsTracker from '@views/dashboards/farm/FarmAlertsTracker'
import SensorValuesList from '@views/dashboards/farm/SensorValuesList'
import SensorRadarChart from '@views/dashboards/farm/SensorRadarChart'
import SensorComparisonChart from '@views/dashboards/farm/SensorComparisonChart'
import FarmAlertsTimeline from '@views/dashboards/farm/FarmAlertsTimeline'
import WaterNeedPrediction from '@views/dashboards/farm/WaterNeedPrediction'
import YieldPredictionChart from '@views/dashboards/farm/YieldPredictionChart'
import HarvestPredictionCard from '@views/dashboards/farm/HarvestPredictionCard'
import SoilMoistureHeatmap from '@views/dashboards/farm/SoilMoistureHeatmap'
import AnomalyDetectionCard from '@views/dashboards/farm/AnomalyDetectionCard'
import NDVIHealthCard from '@views/dashboards/farm/NDVIHealthCard'
import RecommendationsList from '@views/dashboards/farm/RecommendationsList'
import EconomicOverview from '@views/dashboards/farm/EconomicOverview'

// Config & Service
import {
  ROW_IDS,
  ROW_CARDS,
  CARD_GRID_SIZE,
  DEFAULT_FARM_DASHBOARD_CONFIG,
  type RowId,
  type CardId,
  type FarmDashboardConfig
} from '@views/dashboards/farm/farmDashboardConfig'
import { farmDashboardService } from '@/libs/api/services/farmDashboardService'
import FarmDashboardSettingsDropdown from '@views/dashboards/farm/FarmDashboardSettingsDropdown'

const cardRowSx = {
  display: 'flex',
  flexDirection: 'column',
  '& > *': { flex: 1, minHeight: 0 }
}

const CARD_COMPONENTS: Record<CardId, React.ComponentType> = {
  farmOverviewKpis: FarmOverviewKPIs,
  farmWeatherCard: FarmWeatherCard,
  farmAlertsTracker: FarmAlertsTracker,
  sensorValuesList: SensorValuesList,
  sensorRadarChart: SensorRadarChart,
  sensorComparisonChart: SensorComparisonChart,
  anomalyDetectionCard: AnomalyDetectionCard,
  farmAlertsTimeline: FarmAlertsTimeline,
  waterNeedPrediction: WaterNeedPrediction,
  harvestPredictionCard: HarvestPredictionCard,
  yieldPredictionChart: YieldPredictionChart,
  soilMoistureHeatmap: SoilMoistureHeatmap,
  ndviHealthCard: NDVIHealthCard,
  recommendationsList: RecommendationsList,
  economicOverview: EconomicOverview
}

function mergeRowOrderAfterDrag(
  currentRowOrder: string[],
  newVisibleOrder: string[],
  visibleRows: string[]
): string[] {
  const result = [...currentRowOrder]
  let visibleIndex = 0
  for (let i = 0; i < result.length; i++) {
    if (visibleRows.includes(result[i])) {
      result[i] = newVisibleOrder[visibleIndex++]
    }
  }
  return result
}

const FarmDashboardWrapper = () => {
  const t = useTranslations('farmDashboard')
  const { setSlotContent } = useContext(NavbarSlotContext)
  const [config, setConfig] = useState<FarmDashboardConfig>(DEFAULT_FARM_DASHBOARD_CONFIG)

  const cardLabels = useMemo(
    () =>
      Object.fromEntries(
        (
          [
            'farmOverviewKpis',
            'farmWeatherCard',
            'farmAlertsTracker',
            'sensorValuesList',
            'sensorRadarChart',
            'sensorComparisonChart',
            'anomalyDetectionCard',
            'farmAlertsTimeline',
            'waterNeedPrediction',
            'harvestPredictionCard',
            'yieldPredictionChart',
            'soilMoistureHeatmap',
            'ndviHealthCard',
            'recommendationsList',
            'economicOverview'
          ] as CardId[]
        ).map((id) => [id, t(`cards.${id}`)])
      ) as Record<CardId, string>,
    [t]
  )

  const rowLabels = useMemo(
    () =>
      Object.fromEntries(
        (
          [
            'overviewKpis',
            'weatherAlerts',
            'sensorMonitoring',
            'sensorCharts',
            'alertsWater',
            'predictions',
            'soilHeatmap',
            'ndviRecommendations',
            'economic'
          ] as RowId[]
        ).map((id) => [id, t(`rows.${id}`)])
      ) as Record<RowId, string>,
    [t]
  )
  const [cardsData, setCardsData] = useState<Partial<Record<CardId, Record<string, unknown>>>>({})
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)

  const disabledSet = new Set(config.disabledCardIds)

  const hasVisibleCard = useCallback(
    (rowId: string) => {
      const cards = ROW_CARDS[rowId as RowId]
      if (!Array.isArray(cards)) return false
      return cards.some(cardId => !disabledSet.has(cardId))
    },
    [config.disabledCardIds]
  )

  const visibleRowOrder = config.rowOrder.filter(hasVisibleCard)

  const [containerRef, orderedRows, setOrderedRows] = useDragAndDrop(visibleRowOrder, {
    plugins: [animations()],
    dragHandle: '.row-drag-handle'
  })

  useEffect(() => {
    Promise.all([farmDashboardService.getConfig(), farmDashboardService.getAllCards()])
      .then(([configData, cards]) => {
        const validRowOrder = (configData.rowOrder ?? []).filter(
          (id): id is RowId => id in ROW_CARDS
        )
        const merged: FarmDashboardConfig = {
          disabledCardIds: configData.disabledCardIds ?? [],
          rowOrder: validRowOrder.length ? validRowOrder : [...ROW_IDS],
          enableDragReorder: configData.enableDragReorder ?? true
        }
        setConfig(merged)
        setCardsData(cards ?? {})
      })
      .catch(() => setConfig(DEFAULT_FARM_DASHBOARD_CONFIG))
      .finally(() => setLoading(false))
  }, [])

  useEffect(() => {
    setOrderedRows(visibleRowOrder)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [config.disabledCardIds])


  useEffect(() => {
    if (loading) return
    if (JSON.stringify(orderedRows) === JSON.stringify(visibleRowOrder)) return
    const newRowOrder = mergeRowOrderAfterDrag(config.rowOrder, orderedRows, visibleRowOrder)
    setConfig(prev => ({ ...prev, rowOrder: newRowOrder }))
    setSaving(true)
    farmDashboardService
      .updateConfig({ rowOrder: newRowOrder })
      .then(updated => setConfig(updated))
      .catch(() => {})
      .finally(() => setSaving(false))
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [orderedRows])

  const handleToggleDragReorder = useCallback((enabled: boolean) => {
    setConfig(prev => ({ ...prev, enableDragReorder: enabled }))
    setSaving(true)
    farmDashboardService
      .updateConfig({ enableDragReorder: enabled })
      .then(updated => setConfig(updated))
      .finally(() => setSaving(false))
  }, [])

  const handleToggleCard = useCallback(
    (cardId: CardId, disabled: boolean) => {
      const next = disabled
        ? [...config.disabledCardIds, cardId]
        : config.disabledCardIds.filter(id => id !== cardId)
      setConfig(prev => ({ ...prev, disabledCardIds: next }))
      setSaving(true)
      farmDashboardService
        .updateConfig({ disabledCardIds: next })
        .then(updated => setConfig(updated))
        .catch(() => setConfig(prev => ({ ...prev, disabledCardIds: next })))
        .finally(() => setSaving(false))
    },
    [config.disabledCardIds]
  )

  useEffect(() => {
    setSlotContent(
      <FarmDashboardSettingsDropdown
        disabledCardIds={config.disabledCardIds}
        onToggleCard={handleToggleCard}
        enableDragReorder={config.enableDragReorder ?? true}
        onToggleDragReorder={handleToggleDragReorder}
        cardLabels={cardLabels}
        rowLabels={rowLabels}
        rowCards={ROW_CARDS}
        saving={saving}
      />
    )
    return () => setSlotContent(null)
  }, [setSlotContent, config.disabledCardIds, config.enableDragReorder, handleToggleCard, handleToggleDragReorder, saving])

  if (loading) {
    return (
      <Box display='flex' justifyContent='center' alignItems='center' minHeight={200}>
        <CircularProgress />
      </Box>
    )
  }

  return (
    <Box position='relative'>
      <Grid container spacing={6} ref={containerRef as RefObject<HTMLDivElement>}>
        {orderedRows.map((rowId: string) => {
          const cards = ROW_CARDS[rowId as RowId].filter(cardId => !disabledSet.has(cardId))
          if (cards.length === 0) return null

          const isOverviewRow = rowId === 'overviewKpis'

          return (
            <Grid
              key={rowId}
              size={12}
              sx={{
                display: 'flex',
                alignItems: 'flex-start',
                gap: 2,
                ...(config.enableDragReorder !== false && { '&:hover .row-drag-handle': { opacity: 1 } })
              }}
            >
              {config.enableDragReorder !== false && (
                <IconButton
                  className='row-drag-handle'
                  size='small'
                  sx={{
                    opacity: 0.5,
                    cursor: 'grab',
                    flexShrink: 0,
                    mt: 1,
                    '&:active': { cursor: 'grabbing' }
                  }}
                  aria-label={t('settings.dragRow', { row: rowLabels[rowId as RowId] })}
                >
                  <i className='tabler-arrows-move text-textSecondary' />
                </IconButton>
              )}
              <Grid container spacing={6} sx={{ flex: 1, minWidth: 0 }}>
                {isOverviewRow && cards.includes('farmOverviewKpis') && (
                  <FarmOverviewKPIs data={cardsData?.farmOverviewKpis} />
                )}
                {!isOverviewRow &&
                  cards.map((cardId: CardId) => {
                    const size = CARD_GRID_SIZE[cardId]
                    const Component = CARD_COMPONENTS[cardId]
                    if (!Component) return null
                    return (
                      <Grid key={cardId} size={size} sx={cardRowSx}>
                        <Component data={cardsData?.[cardId]} />
                      </Grid>
                    )
                  })}
              </Grid>
            </Grid>
          )
        })}
      </Grid>
    </Box>
  )
}

export default FarmDashboardWrapper
