'use client'

import { useState, useCallback, useEffect, useMemo } from 'react'
import dynamic from 'next/dynamic'
import { useTranslations } from 'next-intl'
import Box from '@mui/material/Box'
import CircularProgress from '@mui/material/CircularProgress'
import Button from '@mui/material/Button'
import CropZoningMap from './CropZoningMap'
import ZoneLegend from './ZoneLegend'
import LayerControl from './LayerControl'
import ZoneDetailPanel from './ZoneDetailPanel'
import CropZoningWeatherSection from './CropZoningWeatherSection'
import { createGridFromPolygon } from './cropZoningUtils'
import {
  cropZoningService,
  type Product,
  type ZoneInitialData,
  type ZoneDetailData,
  type ZoneMapData,
  type ZoneWaterNeedData,
  type ZoneSoilQualityData,
  type ZoneCultivationRiskData
} from '@/libs/api/services/cropZoningService'
import { CROP_COLORS, type CropType } from './cropZoningTypes'
import type { LayerType } from './cropZoningTypes'
import type { MapDrawGeoJSON } from './CropZoningMap'

const MapComponent = dynamic(() => Promise.resolve(CropZoningMap), {
  ssr: false,
  loading: () => (
    <Box className='flex items-center justify-center bs-full min-bs-[400px] rounded-xl bg-action-hover'>
      <CircularProgress size={48} />
    </Box>
  )
})

function isPolygon(geojson: MapDrawGeoJSON): geojson is MapDrawGeoJSON & { geometry: { type: 'Polygon'; coordinates: unknown[] } } {
  return !!geojson?.geometry && (geojson.geometry as { type: string }).type === 'Polygon'
}

export default function CropZoningWrapper() {
  const t = useTranslations('cropZoning')
  const [areaGeoJson, setAreaGeoJson] = useState<MapDrawGeoJSON>(null)
  const [areaLoading, setAreaLoading] = useState(true)
  const [zonesData, setZonesData] = useState<ZoneInitialData[] | null>(null)
  const [zonesWaterNeed, setZonesWaterNeed] = useState<ZoneWaterNeedData[] | null>(null)
  const [zonesSoilQuality, setZonesSoilQuality] = useState<ZoneSoilQualityData[] | null>(null)
  const [zonesCultivationRisk, setZonesCultivationRisk] = useState<ZoneCultivationRiskData[] | null>(null)
  const [products, setProducts] = useState<Product[]>([])
  const [productsLoading, setProductsLoading] = useState(true)
  const [zonesLoading, setZonesLoading] = useState(false)
  const [layerDataLoading, setLayerDataLoading] = useState(false)
  const [activeLayer, setActiveLayer] = useState<LayerType>('crops')
  const [selectedZone, setSelectedZone] = useState<ZoneDetailData | null>(null)
  const [panelOpen, setPanelOpen] = useState(false)
  const [zoneDetailLoading, setZoneDetailLoading] = useState(false)
  const [optimizationKey, setOptimizationKey] = useState(0)

  const productLabels = Object.fromEntries(products.map(p => [p.id, p.label]))

  useEffect(() => {
    cropZoningService
      .getProducts()
      .then(res => setProducts(res.products))
      .catch(() => setProducts([]))
      .finally(() => setProductsLoading(false))
  }, [])

  useEffect(() => {
    setAreaLoading(true)
    cropZoningService
      .getArea()
      .then(res => setAreaGeoJson(res.area as unknown as MapDrawGeoJSON))
      .catch(() => setAreaGeoJson(null))
      .finally(() => setAreaLoading(false))
  }, [])

  const fetchZones = useCallback((geojson: MapDrawGeoJSON) => {
    if (!isPolygon(geojson)) {
      setZonesData(null)
      setZonesWaterNeed(null)
      setZonesSoilQuality(null)
      setZonesCultivationRisk(null)
      return
    }
    setZonesWaterNeed(null)
    setZonesSoilQuality(null)
    setZonesCultivationRisk(null)
    setZonesLoading(true)
    const grid = createGridFromPolygon(geojson as unknown as import('geojson').Feature<import('geojson').Polygon>)
    cropZoningService
      .getZonesInitial({ zones: grid })
      .then(res => setZonesData(res.zones))
      .catch(() => setZonesData(null))
      .finally(() => setZonesLoading(false))
  }, [])

  useEffect(() => {
    if (isPolygon(areaGeoJson)) {
      fetchZones(areaGeoJson)
    } else {
      setZonesData(null)
      setZonesWaterNeed(null)
      setZonesSoilQuality(null)
      setZonesCultivationRisk(null)
    }
  }, [areaGeoJson, optimizationKey, fetchZones])

  const gridForLayers = isPolygon(areaGeoJson)
    ? createGridFromPolygon(areaGeoJson as unknown as import('geojson').Feature<import('geojson').Polygon>)
    : null

  useEffect(() => {
    if (!gridForLayers || zonesLoading) return
    if (activeLayer === 'waterNeed' && zonesWaterNeed === null) {
      setLayerDataLoading(true)
      cropZoningService
        .getZonesWaterNeed({ zones: gridForLayers })
        .then(res => setZonesWaterNeed(res.zones))
        .catch(() => setZonesWaterNeed(null))
        .finally(() => setLayerDataLoading(false))
    } else if (activeLayer === 'soilQuality' && zonesSoilQuality === null) {
      setLayerDataLoading(true)
      cropZoningService
        .getZonesSoilQuality({ zones: gridForLayers })
        .then(res => setZonesSoilQuality(res.zones))
        .catch(() => setZonesSoilQuality(null))
        .finally(() => setLayerDataLoading(false))
    } else if (activeLayer === 'cultivationRisk' && zonesCultivationRisk === null) {
      setLayerDataLoading(true)
      cropZoningService
        .getZonesCultivationRisk({ zones: gridForLayers })
        .then(res => setZonesCultivationRisk(res.zones))
        .catch(() => setZonesCultivationRisk(null))
        .finally(() => setLayerDataLoading(false))
    }
  }, [activeLayer, gridForLayers, zonesLoading, zonesWaterNeed, zonesSoilQuality, zonesCultivationRisk])

  const mapZonesData = useMemo((): ZoneMapData[] | null => {
    const labels = Object.fromEntries(products.map(p => [p.id, p.label]))
    if (activeLayer === 'crops' && zonesData) {
      const isCultivable = (crop: string | null | undefined) =>
        !!crop && crop !== 'uncultivable' && crop.toLowerCase() !== 'uncultivable'
      return zonesData.map(z => {
        const cultivable = isCultivable(z.crop)
        const cropLabel = cultivable ? (labels[z.crop!] ?? z.crop) : 'غیر قابل کشت'
        const tooltipContent = cultivable
          ? `<div style="font-family: inherit; font-size: 12px; padding: 4px 8px; min-width: 160px;">
              <div style="font-weight: 600; margin-bottom: 6px;">${cropLabel}</div>
              <div>درصد تطابق: ${z.matchPercent ?? '-'}%</div>
              <div>نیاز آب: ${z.waterNeed ?? '-'}</div>
              <div>سود تخمینی: ${z.estimatedProfit ?? '-'}</div>
            </div>`
          : `<div style="font-family: inherit; font-size: 12px; padding: 4px 8px; min-width: 160px;">
              <div style="font-weight: 600; margin-bottom: 6px; color: #64748b;">غیر قابل کشت</div>
              <div style="color: #94a3b8;">این بخش برای کشت مناسب تشخیص داده نشده است.</div>
            </div>`
        const color = cultivable ? (CROP_COLORS[z.crop as CropType] ?? '#94a3b8') : '#94a3b8'
        return {
          zoneId: z.zoneId,
          geometry: z.geometry,
          color,
          tooltipContent,
          cultivable,
          zoneInitialData: z
        }
      })
    }
    if (activeLayer === 'waterNeed' && zonesWaterNeed) {
      const levelLabels = { low: 'کم', medium: 'متوسط', high: 'زیاد' }
      return zonesWaterNeed.map(z => ({
        zoneId: z.zoneId,
        geometry: z.geometry,
        color: z.color,
        tooltipContent: `<div style="font-family: inherit; font-size: 12px; padding: 4px 8px; min-width: 160px;">
          <div style="font-weight: 600; margin-bottom: 6px;">نیاز آبی: ${levelLabels[z.level]}</div>
          <div>${z.value ?? '-'}</div>
        </div>`,
        cultivable: false
      }))
    }
    if (activeLayer === 'soilQuality' && zonesSoilQuality) {
      const levelLabels = { low: 'کم', medium: 'متوسط', high: 'زیاد' }
      return zonesSoilQuality.map(z => ({
        zoneId: z.zoneId,
        geometry: z.geometry,
        color: z.color,
        tooltipContent: `<div style="font-family: inherit; font-size: 12px; padding: 4px 8px; min-width: 160px;">
          <div style="font-weight: 600; margin-bottom: 6px;">کیفیت خاک: ${levelLabels[z.level]}</div>
          <div>امتیاز: ${z.score ?? '-'}</div>
        </div>`,
        cultivable: false
      }))
    }
    if (activeLayer === 'cultivationRisk' && zonesCultivationRisk) {
      const levelLabels = { low: 'کم', medium: 'متوسط', high: 'زیاد' }
      return zonesCultivationRisk.map(z => ({
        zoneId: z.zoneId,
        geometry: z.geometry,
        color: z.color,
        tooltipContent: `<div style="font-family: inherit; font-size: 12px; padding: 4px 8px; min-width: 160px;">
          <div style="font-weight: 600; margin-bottom: 6px;">ریسک کشت: ${levelLabels[z.level]}</div>
        </div>`,
        cultivable: false
      }))
    }
    return null
  }, [activeLayer, zonesData, zonesWaterNeed, zonesSoilQuality, zonesCultivationRisk, products])

  const handleAreaChange = useCallback((geojson: MapDrawGeoJSON) => {
    setAreaGeoJson(geojson)
  }, [])

  const handleZoneClick = useCallback((zone: ZoneInitialData) => {
    setZoneDetailLoading(true)
    setPanelOpen(true)
    setSelectedZone(null)
    cropZoningService
      .getZoneDetails(zone.zoneId)
      .then(details => setSelectedZone(details))
      .catch(() => setSelectedZone(null))
      .finally(() => setZoneDetailLoading(false))
  }, [])

  const handleOptimize = useCallback(() => {
    setOptimizationKey(k => k + 1)
  }, [])

  return (
    <Box className='flex flex-col gap-6 is-full'>
      <Box className='relative min-bs-[400px] rounded-xl overflow-hidden' sx={{ height: 'min(60vh, 500px)' }}>
        <Box className='absolute inset-0 z-0'>
          {areaGeoJson ? (
            <MapComponent
              key='crop-zoning-map'
              center={[35.6892, 51.389]}
              zoom={13}
              height='100%'
              activeLayer={activeLayer}
              onAreaChange={handleAreaChange}
              onZoneClick={handleZoneClick}
              optimizationKey={optimizationKey}
              className='min-bs-[400px]'
              initialAreaGeoJson={areaGeoJson}
              zonesData={mapZonesData}
              productLabels={productLabels}
              readOnly
            />
          ) : (
            <Box className='flex items-center justify-center bs-full min-bs-[400px] rounded-xl bg-action-hover' />
          )}
        </Box>

        {(areaLoading || zonesLoading || (activeLayer !== 'crops' && layerDataLoading)) && (
          <Box
            className='absolute inset-0 z-[500] flex items-center justify-center bg-white/60 dark:bg-gray-900/60'
            sx={{ borderRadius: 12 }}
          >
            <CircularProgress size={48} />
          </Box>
        )}

        <LayerControl activeLayer={activeLayer} onLayerChange={setActiveLayer} />

        <ZoneLegend
          activeLayer={activeLayer}
          products={products}
          loading={productsLoading || (activeLayer !== 'crops' && layerDataLoading)}
        />

        {areaGeoJson && (
          <Box className='absolute top-16 end-4 z-[1000]'>
            <Button
                variant='contained'
                color='primary'
                size='medium'
                startIcon={<i className='tabler-refresh text-xl' />}
                onClick={handleOptimize}
                disabled={zonesLoading}
                className='rounded-xl shadow-lg'
            >
              {t('optimizeAgain')}
            </Button>
          </Box>
        )}
      </Box>

      <ZoneDetailPanel
        open={panelOpen}
        onClose={() => setPanelOpen(false)}
        zone={selectedZone}
        products={products}
        loading={zoneDetailLoading}
      />

      <CropZoningWeatherSection />
    </Box>
  )
}
