import React, { useState, useEffect } from 'react'
import { AnimatePresence } from 'framer-motion'
import dayjs from 'dayjs'
import relativeTime from 'dayjs/plugin/relativeTime'
import isBetween from 'dayjs/plugin/isBetween'
import localizedFormat from 'dayjs/plugin/localizedFormat'

import SurveyModal from './widgets/SurveyModal'
import AnnouncementModal from './widgets/AnnouncementModal'
import EventModal from './widgets/EventModal'

import { Container } from '@/components/shared'
import { usePermission } from '@/utils/hooks/usePermission'
import {
  AnnouncementDto,
  EventDto,
  IntranetDashboardDto,
  SurveyAnswerDto,
  SurveyDto,
} from '@/proxy/intranet/models'
import { intranetService } from '@/services/intranet.service'
import { useLocalization } from '@/utils/hooks/useLocalization'
import useLocale from '@/utils/hooks/useLocale'
import { currentLocalDate } from '@/utils/dateUtils'
import { useStoreActions, useStoreState } from '@/store/store'
import Button from '@/components/ui/Button'
import { LuX } from 'react-icons/lu'
import type { DashboardWidgetColumn, DashboardWidgetDefinition } from './dashboardWidget'

dayjs.extend(relativeTime)
dayjs.extend(isBetween)
dayjs.extend(localizedFormat)

const dashboardColumns: DashboardWidgetColumn[] = ['left', 'center', 'right']

type DashboardWidgetModule = { dashboardWidget?: DashboardWidgetDefinition }

const dashboardWidgets = Object.values(
  import.meta.glob<DashboardWidgetModule>(['./widgets/*.tsx', './SocialWall/index.tsx'], {
    eager: true,
  }),
)
  .map((module) => module.dashboardWidget)
  .filter((widget): widget is DashboardWidgetDefinition => Boolean(widget))
  .sort((left, right) => left.order - right.order)

const layoutPresets = [
  {
    id: 'default',
    columns: [3, 6, 3],
    labelKey: '::App.Platform.Intranet.Dashboard.Layout.Default',
  },
  {
    id: 'wide-center',
    columns: [2, 8, 2],
    labelKey: '::App.Platform.Intranet.Dashboard.Layout.CenterFocus',
  },
  {
    id: 'balanced',
    columns: [4, 4, 4],
    labelKey: '::App.Platform.Intranet.Dashboard.Layout.Balanced',
  },
  {
    id: 'wide-left',
    columns: [4, 6, 2],
    labelKey: '::App.Platform.Intranet.Dashboard.Layout.WideLeft',
  },
  {
    id: 'wide-right',
    columns: [2, 6, 4],
    labelKey: '::App.Platform.Intranet.Dashboard.Layout.WideRight',
  },
] as const

const columnSpanClasses: Record<number, string> = {
  2: 'lg:col-span-2',
  3: 'lg:col-span-3',
  4: 'lg:col-span-4',
  6: 'lg:col-span-6',
  8: 'lg:col-span-8',
}

const IntranetDashboard: React.FC = () => {
  const { checkPermission } = usePermission()
  const [selectedAnnouncement, setSelectedAnnouncement] = useState<AnnouncementDto | null>(null)
  const [selectedEvent, setSelectedEvent] = useState<EventDto | null>(null)
  const [selectedSurvey, setSelectedSurvey] = useState<SurveyDto | null>(null)
  const [showSurveyModal, setShowSurveyModal] = useState(false)
  const [isDesignMode, setIsDesignMode] = useState(false)
  const { dashboardLayout: selectedLayout, hiddenWidgetIds, widgetOrder } = useStoreState(
    (state) => state.admin.dashboard,
  )
  const {
    setDashboardLayout,
    setHiddenWidgetIds,
    setWidgetOrder,
    reset: resetDashboard,
  } = useStoreActions((actions) => actions.admin.dashboard)

  const [intranetDashboard, setIntranetDashboard] = useState<IntranetDashboardDto>()
  const { translate } = useLocalization()
  const currentLocale = useLocale()

  const fetchIntranetDashboard = async () => {
    try {
      const dashboard = await intranetService.getDashboard()
      if (dashboard.data) {
        setIntranetDashboard(dashboard.data)
      }
    } catch {
      // hata apiService tarafından ele alınıyor
    }
  }

  useEffect(() => {
    fetchIntranetDashboard()
  }, [])

  const [dragState, setDragState] = useState<{
    draggedId: string | null
    targetColumn: DashboardWidgetColumn | null
    targetIndex: number | null
  }>({
    draggedId: null,
    targetColumn: null,
    targetIndex: null,
  })

  const handleTakeSurvey = (survey: SurveyDto) => {
    setSelectedSurvey(survey)
    setShowSurveyModal(true)
  }

  const handleSubmitSurvey = async (answers: SurveyAnswerDto[]) => {
    if (!selectedSurvey) return
    try {
      await intranetService.createSurveyResponse(
        selectedSurvey.id,
        answers.map((a) => ({
          questionId: a.questionId,
          questionType: a.questionType,
          value: a.value !== undefined && a.value !== null ? String(a.value) : '',
        })),
      )
      await fetchIntranetDashboard()
    } catch (e) {
      console.error('Survey submit error', e)
    }
    setShowSurveyModal(false)
    setSelectedSurvey(null)
  }

  const handleEventLikeChange = (updatedEvent: EventDto) => {
    setSelectedEvent((current) => (current ? { ...current, ...updatedEvent } : updatedEvent))
    setIntranetDashboard((current) =>
      current
        ? {
            ...current,
            events: current.events.map((event) =>
              event.id === updatedEvent.id ? { ...event, ...updatedEvent } : event,
            ),
          }
        : current,
    )
  }

  const handleAnnouncementLikeChange = (updatedAnnouncement: AnnouncementDto) => {
    setSelectedAnnouncement((current) =>
      current ? { ...current, ...updatedAnnouncement } : updatedAnnouncement,
    )
    setIntranetDashboard((current) =>
      current
        ? {
            ...current,
            announcements: current.announcements.map((announcement) =>
              announcement.id === updatedAnnouncement.id
                ? { ...announcement, ...updatedAnnouncement }
                : announcement,
            ),
          }
        : current,
    )
  }

  const grantedPolicies = useStoreState((state) => state.abpConfig?.config?.auth.grantedPolicies)

  const initializeDefaultOrder = () => {
    const defaultOrder: Record<DashboardWidgetColumn, string[]> = {
      left: [],
      center: [],
      right: [],
    }
    dashboardWidgets.forEach((widget) => {
      if (checkPermission(widget.permission)) defaultOrder[widget.column].push(widget.id)
    })
    setWidgetOrder(defaultOrder)
  }

  useEffect(() => {
    if (!grantedPolicies) return

    const hasSavedOrder = dashboardColumns.some((column) => widgetOrder[column].length > 0)
    if (!hasSavedOrder) {
      initializeDefaultOrder()
      return
    }

    // Kayıtlı sıralamayı tekilleştir ve henüz yerleştirilmemiş widget'ları ekle
    const order: Record<DashboardWidgetColumn, string[]> = {
      left: [...new Set(widgetOrder.left || [])],
      center: [...new Set(widgetOrder.center || [])],
      right: [...new Set(widgetOrder.right || [])],
    }

    const allAssigned = new Set([...order.left, ...order.center, ...order.right])
    dashboardWidgets.forEach((widget) => {
      if (!allAssigned.has(widget.id) && checkPermission(widget.permission)) {
        order[widget.column].push(widget.id)
      }
    })

    setWidgetOrder(order)
  }, [grantedPolicies])

  const setWidgetVisibility = (widgetId: string, visible: boolean) => {
    const next = visible
      ? hiddenWidgetIds.filter((id) => id !== widgetId)
      : [...new Set([...hiddenWidgetIds, widgetId])]
    setHiddenWidgetIds(next)
  }

  const activeLayout =
    layoutPresets.find((layout) => layout.id === selectedLayout) || layoutPresets[0]
  const hiddenWidgets = dashboardWidgets.filter(
    (widget) => hiddenWidgetIds.includes(widget.id) && checkPermission(widget.permission),
  )

  const handleDragStart = (e: React.DragEvent, widgetId: string) => {
    setDragState({ draggedId: widgetId, targetColumn: null, targetIndex: null })
    e.dataTransfer.effectAllowed = 'move'
    e.dataTransfer.setData('widgetId', widgetId)
  }

  const handleDragEnterWidget = (
    e: React.DragEvent,
    column: DashboardWidgetColumn,
    index: number,
  ) => {
    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()
    if (e.clientY - rect.top < rect.height * 0.3) {
      setDragState((prev) => ({ ...prev, targetColumn: column, targetIndex: index }))
    } else {
      setDragState((prev) => ({ ...prev, targetColumn: column, targetIndex: null }))
    }
  }

  const handleDragEnterColumn = (column: DashboardWidgetColumn) => {
    setDragState((prev) => ({ ...prev, targetColumn: column, targetIndex: null }))
  }

  const handleDragLeaveColumn = () => {
    setDragState((prev) => ({ ...prev, targetColumn: null, targetIndex: null }))
  }

  const handleDrop = (
    e: React.DragEvent,
    targetColumn: DashboardWidgetColumn,
    targetIndex?: number,
  ) => {
    e.preventDefault()
    e.stopPropagation()

    const widgetId = e.dataTransfer.getData('widgetId')
    if (!widgetId) return

    const newOrder = { ...widgetOrder }

    dashboardColumns.forEach((col) => {
      newOrder[col] = newOrder[col].filter((id) => id !== widgetId)
    })

    if (targetIndex !== undefined) {
      newOrder[targetColumn].splice(targetIndex, 0, widgetId)
    } else {
      newOrder[targetColumn].push(widgetId)
    }

    setWidgetOrder(newOrder)
    setDragState({ draggedId: null, targetColumn: null, targetIndex: null })
  }

  const handleDragEnd = () => {
    setDragState({ draggedId: null, targetColumn: null, targetIndex: null })
  }

  const handleColumnDragOver = (
    e: React.DragEvent<HTMLDivElement>,
    column: DashboardWidgetColumn,
  ) => {
    if (!isDesignMode) return
    e.preventDefault()

    const now = Date.now()
    const lastUpdate = Number(e.currentTarget.dataset.lastColumnUpdate || 0)
    if (now - lastUpdate > 150) {
      e.currentTarget.dataset.lastColumnUpdate = now.toString()
      handleDragEnterColumn(column)
    }
  }

  const handleColumnDrop = (e: React.DragEvent<HTMLDivElement>, column: DashboardWidgetColumn) => {
    if (!isDesignMode) return
    handleDrop(e, column, widgetOrder[column].length)
  }

  const renderWidgets = (column: DashboardWidgetColumn) => {
    const columnWidgets = widgetOrder[column] || []

    const uniqueWidgets = [...new Set(columnWidgets)]

    return uniqueWidgets
      .map((widgetId, index) => {
        const metadata = dashboardWidgets.find((w) => w.id === widgetId)
        if (
          !metadata ||
          !checkPermission(metadata.permission) ||
          hiddenWidgetIds.includes(widgetId)
        )
          return null

        const isDragging = dragState.draggedId === widgetId
        const isDropTarget = dragState.targetColumn === column && dragState.targetIndex === index

        return (
          <div key={`${column}-${widgetId}`} className="relative group">
            {isDesignMode && isDropTarget && !isDragging && (
              <div className="absolute -top-5 left-0 right-0 z-20 animate-in fade-in slide-in-from-top-2 duration-300">
                <div className="h-2 bg-gradient-to-r from-transparent via-blue-500 to-transparent rounded-full shadow-lg" />
                <div className="absolute -top-4 left-1/2 -translate-x-1/2 bg-gradient-to-r from-blue-500 to-blue-600 text-white text-xs px-4 py-2 rounded-full whitespace-nowrap shadow-xl font-semibold flex items-center gap-2 border-2 border-white dark:border-gray-800">
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth={2}
                      d="M19 14l-7 7m0 0l-7-7m7 7V3"
                    />
                  </svg>
                  <span>{translate('::App.Platform.Intranet.Dashboard.DropHere')}</span>
                </div>
              </div>
            )}

            <div
              draggable={isDesignMode}
              onDragStart={(e) => {
                if (isDesignMode) {
                  handleDragStart(e, widgetId)
                }
              }}
              onDragOver={(e) => {
                if (!isDesignMode) return
                e.preventDefault()
                e.stopPropagation()
                const now = Date.now()
                if (
                  !e.currentTarget.dataset.lastUpdate ||
                  now - parseInt(e.currentTarget.dataset.lastUpdate) > 150
                ) {
                  e.currentTarget.dataset.lastUpdate = now.toString()
                  handleDragEnterWidget(e, column, index)
                }
              }}
              onDragLeave={() => {
                if (isDesignMode) {
                  setDragState((prev) => ({
                    ...prev,
                    targetColumn: prev.targetColumn,
                    targetIndex: null,
                  }))
                }
              }}
              onDrop={(e) => {
                if (!isDesignMode) return
                e.stopPropagation()

                const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()
                if (e.clientY - rect.top < rect.height * 0.3) {
                  handleDrop(e, column, index)
                } else {
                  handleDrop(e, column, index + 1)
                }
              }}
              onDragEnd={handleDragEnd}
              className={`
              relative 
              ${
                isDesignMode
                  ? `border-2 border-dashed rounded-lg cursor-move
                   ${
                     isDragging
                       ? 'border-blue-400 opacity-70 bg-blue-50/30 dark:bg-blue-900/10'
                       : 'border-gray-300 dark:border-gray-600 hover:border-blue-400 dark:hover:border-blue-500 hover:shadow-md'
                   }
                   transition-all duration-300 ease-out`
                  : 'border-0 transition-none'
              }
            `}
              style={{
                touchAction: isDesignMode ? 'none' : 'pan-y',
                transition:
                  'border-color 0.3s ease-out, opacity 0.3s ease-out, box-shadow 0.3s ease-out',
                willChange: isDragging ? 'opacity' : 'auto',
              }}
            >
              {isDesignMode && !isDragging && (
                <button
                  type="button"
                  className="absolute right-2 top-2 z-20 flex h-7 w-7 items-center justify-center rounded-full bg-white text-gray-500 shadow-sm dark:bg-gray-800 dark:text-gray-300"
                  title={translate('::App.Platform.Intranet.Dashboard.HideWidget')}
                  aria-label={`${translate('::App.Platform.Intranet.Dashboard.HideWidget')}: ${translate(metadata.labelKey)}`}
                  draggable={false}
                  onMouseDown={(e) => e.stopPropagation()}
                  onDragStart={(e) => e.stopPropagation()}
                  onClick={(e) => {
                    e.stopPropagation()
                    setWidgetVisibility(widgetId, false)
                  }}
                >
                  <LuX className="h-4 w-4" aria-hidden="true" />
                </button>
              )}
              {isDesignMode && isDragging && (
                <div className="absolute inset-0 bg-white/60 dark:bg-gray-900/40 rounded-lg z-10 flex items-center justify-center backdrop-blur-[1px] transition-opacity duration-300">
                  <div className="bg-gradient-to-r from-blue-500 to-blue-600 text-white px-4 py-2 rounded-lg font-medium shadow-lg flex items-center gap-2">
                    <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M7 16V4m0 0L3 8m4-4l4 4m6 0v12m0 0l4-4m-4 4l-4-4"
                      />
                    </svg>
                    <span>{translate('::App.Platform.Intranet.Dashboard.Moving')}</span>
                  </div>
                </div>
              )}
              <div
                className={`${isDesignMode ? 'p-1.5' : ''} transition-all duration-500 ease-out`}
              >
                {metadata.render({
                  dashboard: intranetDashboard,
                  openAnnouncement: setSelectedAnnouncement,
                  openEvent: setSelectedEvent,
                  takeSurvey: handleTakeSurvey,
                })}
              </div>
            </div>
          </div>
        )
      })
      .filter(Boolean)
  }

  return (
    <Container>
      <div className="mx-auto space-y-4">
        <div className="relative flex flex-wrap items-center justify-between gap-4 lg:min-h-10">
          <div className="flex items-center gap-2">
            <label
              htmlFor="design-mode-toggle"
              className="text-sm font-medium text-gray-700 dark:text-gray-300 cursor-pointer"
            >
              🎨 {translate('::App.Platform.Intranet.Dashboard.DesignMode')}
            </label>
            <Button
              id="design-mode-toggle"
              onClick={() => setIsDesignMode(!isDesignMode)}
              variant="plain"
              shape="none"
              className={`
                  relative !inline-flex !h-6 !w-11 !min-w-11 !items-center !justify-start !rounded-full !border-0 !px-0 transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
                  ${isDesignMode ? '!bg-blue-600 hover:!bg-blue-600' : '!bg-gray-300 hover:!bg-gray-300 dark:!bg-gray-600 dark:hover:!bg-gray-600'}
                `}
              role="switch"
              aria-checked={isDesignMode}
            >
              <span
                className={`
                    inline-block h-4 w-4 transform rounded-full bg-white transition-transform
                    ${isDesignMode ? 'translate-x-6' : 'translate-x-1'}
                  `}
              />
            </Button>
            {isDesignMode && (
              <Button
                onClick={() => {
                  resetDashboard()
                  initializeDefaultOrder()
                }}
                variant="plain"
                shape="none"
                className="!h-auto !items-center gap-1 !rounded-none !px-0 !py-0 text-sm text-gray-500 transition-colors hover:!bg-transparent hover:text-gray-700 active:!bg-transparent focus:!bg-transparent dark:text-gray-400 dark:hover:text-gray-200"
                title={translate('::App.Platform.Intranet.Dashboard.ResetTitle')}
              >
                🔄 {translate('::Reset')}
              </Button>
            )}
          </div>

          {isDesignMode && (
            <div
              className="order-last flex w-full items-center justify-center gap-1 lg:absolute lg:left-1/2 lg:top-1/2 lg:order-none lg:w-auto lg:-translate-x-1/2 lg:-translate-y-1/2"
              role="group"
              aria-label={translate('::App.Platform.Intranet.Dashboard.Layout')}
            >
              <span className="mr-1 text-sm text-gray-500 dark:text-gray-400">
                {translate('::App.Platform.Intranet.Dashboard.Layout')}
              </span>
              {layoutPresets.map((layout) => (
                <Button
                  key={layout.id}
                  type="button"
                  variant="plain"
                  shape="none"
                  onClick={() => setDashboardLayout(layout.id)}
                  className={`!h-8 !rounded-md !px-2 ${selectedLayout === layout.id ? '!bg-blue-600 text-white hover:!bg-blue-600' : '!bg-gray-100 text-gray-600 hover:!bg-gray-200 dark:!bg-gray-700 dark:text-gray-200'}`}
                  title={`${translate(layout.labelKey)} (${layout.columns.join(' / ')})`}
                  aria-label={`${translate(layout.labelKey)} (${layout.columns.join(' / ')})`}
                  aria-pressed={selectedLayout === layout.id}
                >
                  <span className="flex h-4 w-12 gap-0.5" aria-hidden="true">
                    {layout.columns.map((width, index) => (
                      <span
                        key={index}
                        className="h-full rounded-sm bg-current opacity-70"
                        style={{ flex: width }}
                      />
                    ))}
                  </span>
                </Button>
              ))}
            </div>
          )}

          <p className="mt-1 text-gray-600 dark:text-gray-400">
            <span className="font-medium">{translate('::AI.Welcome')},</span>{' '}
            {currentLocalDate(new Date(), currentLocale || 'tr')}
          </p>
        </div>

        {isDesignMode && hiddenWidgets.length > 0 && (
          <div className="flex flex-wrap items-center gap-1">
            <span className="mr-1 text-sm text-gray-500 dark:text-gray-400">
              {translate('::App.Platform.Intranet.Dashboard.HiddenWidgets')}:
            </span>
            {hiddenWidgets.map((widget) => (
              <Button
                key={widget.id}
                type="button"
                variant="plain"
                shape="none"
                className="!h-8 !rounded-md !bg-emerald-50 !px-2 text-xs text-emerald-700 hover:!bg-emerald-100 dark:!bg-emerald-950 dark:text-emerald-300"
                onClick={() => setWidgetVisibility(widget.id, true)}
                title={translate('::App.Platform.Intranet.Dashboard.ShowWidget')}
              >
                + {translate(widget.labelKey)}
              </Button>
            ))}
          </div>
        )}

        <div className="grid grid-cols-1 lg:grid-cols-12">
          {dashboardColumns.map((column, index) => {
            const isEmptyDropTarget =
              isDesignMode && dragState.targetColumn === column && widgetOrder[column].length === 0

            return (
              <div
                key={column}
                className={`${columnSpanClasses[activeLayout.columns[index]]} min-h-[100px] space-y-6 rounded-xl p-1 ${
                  isDesignMode &&
                  dragState.targetColumn === column &&
                  dragState.targetIndex === null
                    ? 'bg-blue-50/80 ring-2 ring-blue-300 shadow-lg dark:bg-blue-900/20 dark:ring-blue-600'
                    : 'bg-transparent'
                } transition-all duration-700 ease-out`}
                onDragOver={(e) => handleColumnDragOver(e, column)}
                onDragLeave={handleDragLeaveColumn}
                onDrop={(e) => handleColumnDrop(e, column)}
              >
                {renderWidgets(column)}
                {isEmptyDropTarget && (
                  <div className="flex h-40 items-center justify-center rounded-xl border-2 border-dashed border-blue-300 bg-blue-50/50 dark:border-blue-600 dark:bg-blue-900/10">
                    <span className="font-medium text-blue-600 dark:text-blue-400">
                      {translate('::App.Platform.Intranet.Dashboard.DropWidgetHere')}
                    </span>
                  </div>
                )}
              </div>
            )
          })}
        </div>
      </div>

      <AnimatePresence>
        {showSurveyModal && selectedSurvey && (
          <SurveyModal
            survey={selectedSurvey}
            onClose={() => setShowSurveyModal(false)}
            onSubmit={handleSubmitSurvey}
          />
        )}
      </AnimatePresence>

      <AnimatePresence>
        {selectedEvent && (
          <EventModal
            event={selectedEvent}
            onClose={() => setSelectedEvent(null)}
            onLikeChange={handleEventLikeChange}
          />
        )}
      </AnimatePresence>

      <AnimatePresence>
        {selectedAnnouncement && (
          <AnnouncementModal
            announcement={selectedAnnouncement}
            onClose={() => setSelectedAnnouncement(null)}
            onLikeChange={handleAnnouncementLikeChange}
          />
        )}
      </AnimatePresence>
    </Container>
  )
}

export default IntranetDashboard
