import React, { useEffect, useMemo, useState } from 'react';
import { useParams, useSearchParams } from 'react-router-dom';
import styled from 'styled-components';
import toast from 'react-hot-toast';
import {
  DndContext,
  DragOverlay,
  PointerSensor,
  useDraggable,
  useDroppable,
  useSensor,
  useSensors,
  type DragEndEvent,
} from '@dnd-kit/core';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Button, Select } from '@/shared/components/ui';
import { HiPlus } from 'react-icons/hi';
import { CreateSprintModal } from '@/features/projects/components/CreateSprintModal';
import { ContentPanel } from '@/shared/components/layout/ContentPanel';
import { PageSection } from '@/shared/components/layout/PageSection';
import { PanelLoadingState, PanelEmpty } from '@/shared/components/ui/PageState';
import { ProjectPageShell } from '@/features/projects/components/ProjectPageShell';
import { BacklogItemCard } from '@/features/projects/components/BacklogItemCard';
import { ResizableSplitPane } from '@/features/projects/components/ResizableSplitPane';
import { CapacityBar } from '@/features/projects/components/CapacityBar';
import { SprintTeamPanel } from '@/features/projects/components/SprintTeamPanel';
import { SprintHealthBreakdown } from '@/features/projects/components/SprintHealthBreakdown';
import { AgileMetricsSection } from '@/features/projects/components/projectsLayout';
import { useProject } from '@/features/projects/hooks/useProject';
import { useProjectBacklog } from '@/features/projects/hooks/useProjectBacklog';
import { useProjectSprints } from '@/features/projects/hooks/useProjectSprints';
import { useSprintTickets } from '@/features/projects/hooks/useSprintTickets';
import { useSprintCapacity } from '@/features/projects/hooks/useProjectAnalytics';
import { useLocale } from '@/app/providers/LocaleProvider';
import { useProjectPermissions } from '@/features/projects/hooks/useProjectPermissions';
import {
  moveTicketToBacklog,
  moveTicketToSprint,
} from '@/features/projects/services/projectService';
import { backlogQueryKey } from '@/features/projects/hooks/useProjectBacklog';
import { sprintTicketsQueryKey } from '@/features/projects/hooks/useSprintTickets';
import type { ProjectWorkItem } from '@/features/projects/types/project.types';

const PlanningToolbar = styled.div`
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: ${({ theme }) => theme.spacing[4]};
  margin-bottom: ${({ theme }) => theme.spacing[6]};
`;

const CounterRow = styled.div`
  display: flex;
  flex-wrap: wrap;
  gap: ${({ theme }) => theme.spacing[6]};
  font-size: ${({ theme }) => theme.typography.fontSize.sm};
  color: ${({ theme }) => theme.colors.text.secondary};

  strong {
    display: block;
    font-size: ${({ theme }) => theme.typography.fontSize.xl};
    color: ${({ theme }) => theme.colors.text.primary};
    margin-top: ${({ theme }) => theme.spacing[1]};
  }
`;

const Column = styled.div<{ $active?: boolean }>`
  min-height: 280px;
  padding: ${({ theme }) => theme.spacing[4]};
  border-radius: ${({ theme }) => theme.borderRadius.md};
  border: 2px dashed
    ${({ theme, $active }) => ($active ? theme.colors.primary : theme.colors.borderSoft)};
  background: ${({ theme }) => theme.colors.surfaceInset};
  flex: 1;
  display: flex;
  flex-direction: column;
`;

const ColumnTitle = styled.h3`
  margin: 0 0 ${({ theme }) => theme.spacing[4]};
  font-size: ${({ theme }) => theme.typography.fontSize.lg};
  font-weight: ${({ theme }) => theme.typography.fontWeight.semibold};
`;

const Stack = styled.div`
  display: flex;
  flex-direction: column;
  gap: ${({ theme }) => theme.spacing[4]};
  flex: 1;
`;

const CapacityPanel = styled(ContentPanel)`
  margin-bottom: ${({ theme }) => theme.spacing[6]};
`;

function DraggableCard({
  item,
  projectId,
  dragEnabled,
}: {
  item: ProjectWorkItem;
  projectId: string;
  dragEnabled: boolean;
}) {
  const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
    id: item.id,
    data: { item },
    disabled: !dragEnabled,
  });

  if (!dragEnabled) {
    return <BacklogItemCard item={item} projectId={projectId} showMoveToSprint={false} />;
  }

  return (
    <div ref={setNodeRef} {...listeners} {...attributes} style={{ opacity: isDragging ? 0.5 : 1 }}>
      <BacklogItemCard item={item} projectId={projectId} showMoveToSprint={false} />
    </div>
  );
}

function DropColumn({
  id,
  title,
  count,
  mdTotal,
  children,
}: {
  id: string;
  title: string;
  count: number;
  mdTotal: number;
  children: React.ReactNode;
}) {
  const { setNodeRef, isOver } = useDroppable({ id });
  const { t } = useLocale();

  return (
    <Column ref={setNodeRef} $active={isOver}>
      <ColumnTitle>
        {title} ({count})
      </ColumnTitle>
      <CounterRow>
        <div>
          <span>{t('projects:planning.itemCount')}</span>
          <strong>{count}</strong>
        </div>
        <div>
          <span>{t('projects:manDay.committed')}</span>
          <strong>
            {mdTotal} {t('projects:manDay.unit')}
          </strong>
        </div>
      </CounterRow>
      <Stack>{children}</Stack>
    </Column>
  );
}

const SprintPlanningPage: React.FC = () => {
  const { id } = useParams<{ id: string }>();
  const [searchParams] = useSearchParams();
  const { t } = useLocale();
  const { data: project } = useProject(id);
  const { readOnly, canPlanCapacity } = useProjectPermissions(project);
  const dragEnabled = !readOnly;
  const sprintTeamReadOnly = readOnly || !canPlanCapacity;
  const queryClient = useQueryClient();
  const [sprintId, setSprintId] = useState('');
  const [activeItem, setActiveItem] = useState<ProjectWorkItem | null>(null);
  const [createModalOpen, setCreateModalOpen] = useState(false);

  const { data: backlog, isLoading: backlogLoading } = useProjectBacklog(id);
  const { data: sprints } = useProjectSprints(id);

  const plannedSprints = useMemo(
    () => (sprints ?? []).filter((s) => !['completed', 'cancelled', 'archived'].includes(s.status)),
    [sprints],
  );

  const effectiveSprintId = useMemo(() => {
    if (sprintId && plannedSprints.some((s) => s.id === sprintId)) {
      return sprintId;
    }
    return (
      plannedSprints.find((s) => s.status === 'active')?.id ??
      plannedSprints[0]?.id ??
      ''
    );
  }, [sprintId, plannedSprints]);

  useEffect(() => {
    const requestedSprint = searchParams.get('sprint');
    if (requestedSprint && plannedSprints.some((s) => s.id === requestedSprint)) {
      setSprintId(requestedSprint);
      return;
    }
    if (!plannedSprints.length) {
      return;
    }
    if (!sprintId || !plannedSprints.some((s) => s.id === sprintId)) {
      setSprintId(effectiveSprintId);
    }
  }, [plannedSprints, sprintId, effectiveSprintId, searchParams]);

  const { data: sprintItems, isLoading: sprintLoading } = useSprintTickets(id, effectiveSprintId);
  const { data: capacity } = useSprintCapacity(id, effectiveSprintId);

  const invalidate = () => {
    if (!id) return;
    void queryClient.invalidateQueries({ queryKey: backlogQueryKey(id) });
    if (effectiveSprintId) {
      void queryClient.invalidateQueries({
        queryKey: sprintTicketsQueryKey(id, effectiveSprintId),
      });
      void queryClient.invalidateQueries({
        queryKey: ['projects', id, 'sprints', effectiveSprintId, 'capacity'],
      });
    }
  };

  const moveMutation = useMutation({
    mutationFn: async ({
      ticketId,
      target,
      targetSprintId,
    }: {
      ticketId: string;
      target: 'backlog' | 'sprint';
      targetSprintId?: string;
    }) => {
      if (target === 'backlog') {
        return moveTicketToBacklog(id!, ticketId);
      }
      return moveTicketToSprint(id!, ticketId, targetSprintId!);
    },
    onSuccess: invalidate,
  });

  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } }));

  const backlogItems = useMemo(() => backlog?.items ?? [], [backlog?.items]);
  const sprintTickets = useMemo(() => sprintItems ?? [], [sprintItems]);

  const sumMd = (items: ProjectWorkItem[]) =>
    items.reduce((sum, i) => sum + (i.estimate_md ?? 0), 0);

  const allItems = useMemo(() => {
    const map = new Map<string, ProjectWorkItem>();
    backlogItems.forEach((i) => map.set(i.id, i));
    sprintTickets.forEach((i) => map.set(i.id, i));
    return map;
  }, [backlogItems, sprintTickets]);

  const onDragEnd = (event: DragEndEvent) => {
    if (!dragEnabled) return;
    setActiveItem(null);
    const { active, over } = event;
    if (!over || !id) return;

    const ticketId = String(active.id);
    const overId = String(over.id);

    const droppedOnBacklog =
      overId === 'backlog-drop' || backlogItems.some((item) => item.id === overId);

    if (droppedOnBacklog) {
      moveMutation.mutate({ ticketId, target: 'backlog' });
      return;
    }

    const sprintPrefix = 'sprint-drop-';
    const sprintFromColumn = overId.startsWith(sprintPrefix)
      ? overId.slice(sprintPrefix.length)
      : null;
    const droppedOnSprint =
      sprintFromColumn !== null || sprintTickets.some((item) => item.id === overId);

    if (droppedOnSprint) {
      const targetSprint = (sprintFromColumn || effectiveSprintId).trim();
      if (!targetSprint) {
        toast.error(t('projects:planning.noSprintSelected'));
        return;
      }
      moveMutation.mutate({ ticketId, target: 'sprint', targetSprintId: targetSprint });
    }
  };

  return (
    <ProjectPageShell projectId={id}>
      {({ project }) => (
        <PageSection title={t('projects:planning.title')}>
          <PlanningToolbar>
            <Select
              label={t('projects:planning.sprint')}
              value={effectiveSprintId}
              onChange={(e) => setSprintId(e.target.value)}
              options={plannedSprints.map((s) => ({ value: s.id, label: s.name }))}
              disabled={plannedSprints.length === 0}
            />
            {dragEnabled && (
              <Button
                type="button"
                variant="primary"
                size="lg"
                icon={<HiPlus aria-hidden />}
                onClick={() => setCreateModalOpen(true)}
              >
                {t('projects:backlog.createSprint')}
              </Button>
            )}
            <CounterRow>
              <div>
                <span>{t('projects:planning.backlogCount')}</span>
                <strong>{backlogItems.length}</strong>
              </div>
              <div>
                <span>{t('projects:planning.sprintCount')}</span>
                <strong>{sprintTickets.length}</strong>
              </div>
            </CounterRow>
          </PlanningToolbar>

          {effectiveSprintId && (
            <AgileMetricsSection style={{ marginTop: 0 }}>
              {capacity && (
                <CapacityPanel variant="inset" padding="md">
                  <h4 style={{ margin: `0 0 ${'1rem'}` }}>{t('projects:manDay.sprintLoad')}</h4>
                  <CapacityBar
                    committedMd={capacity.committed_md}
                    capacityMd={capacity.capacity_md}
                  />
                </CapacityPanel>
              )}
              <SprintTeamPanel
                projectId={id!}
                sprintId={effectiveSprintId}
                readOnly={sprintTeamReadOnly}
              />
              {(() => {
                const sprint = sprints?.find((s) => s.id === effectiveSprintId);
                return sprint?.executive_health_detail ? (
                  <SprintHealthBreakdown health={sprint.executive_health_detail} />
                ) : null;
              })()}
            </AgileMetricsSection>
          )}

          {plannedSprints.length === 0 ? (
            <>
              <PanelEmpty
                title={t('projects:planning.noSprints')}
                hint={t('projects:planning.noSprintsHint')}
              />
              {dragEnabled && (
                <div style={{ marginTop: '1rem' }}>
                  <Button
                    type="button"
                    variant="primary"
                    size="lg"
                    icon={<HiPlus aria-hidden />}
                    onClick={() => setCreateModalOpen(true)}
                  >
                    {t('projects:backlog.createSprint')}
                  </Button>
                </div>
              )}
            </>
          ) : (
            <DndContext
              sensors={sensors}
              onDragStart={(e) => {
                const item = allItems.get(String(e.active.id));
                if (item) setActiveItem(item);
              }}
              onDragEnd={onDragEnd}
            >
              <ResizableSplitPane
                left={
                  <DropColumn
                    id="backlog-drop"
                    title={t('projects:nav.backlog')}
                    count={backlogItems.length}
                    mdTotal={sumMd(backlogItems)}
                  >
                    {backlogLoading ? (
                      <PanelLoadingState label={t('projects:states.loading')} />
                    ) : backlogItems.length === 0 ? (
                      <PanelEmpty
                        title={t('projects:backlog.empty')}
                        hint={t('projects:planning.dropHint')}
                      />
                    ) : (
                      backlogItems.map((item) => (
                        <DraggableCard
                          key={item.id}
                          item={item}
                          projectId={project.id}
                          dragEnabled={dragEnabled}
                        />
                      ))
                    )}
                  </DropColumn>
                }
                right={
                  <DropColumn
                    id={`sprint-drop-${effectiveSprintId}`}
                    title={t('projects:planning.sprintColumn')}
                    count={sprintTickets.length}
                    mdTotal={sumMd(sprintTickets)}
                  >
                    {sprintLoading ? (
                      <PanelLoadingState label={t('projects:states.loading')} />
                    ) : sprintTickets.length === 0 ? (
                      <PanelEmpty
                        title={t('projects:sprint.empty')}
                        hint={t('projects:planning.dropHint')}
                      />
                    ) : (
                      sprintTickets.map((item) => (
                        <DraggableCard
                          key={item.id}
                          item={item}
                          projectId={project.id}
                          dragEnabled={dragEnabled}
                        />
                      ))
                    )}
                  </DropColumn>
                }
              />
              <DragOverlay>
                {activeItem ? (
                  <BacklogItemCard
                    item={activeItem}
                    projectId={project.id}
                    showMoveToSprint={false}
                  />
                ) : null}
              </DragOverlay>
            </DndContext>
          )}
          <CreateSprintModal
            projectId={project.id}
            isOpen={createModalOpen}
            onClose={() => setCreateModalOpen(false)}
          />
        </PageSection>
      )}
    </ProjectPageShell>
  );
};

export default SprintPlanningPage;
