import React from 'react'
import styled from 'styled-components'
import { cursor, shadow, theme } from '@planview/pv-utilities'
import { useDndContext } from '@dnd-kit/core'
import type { Column } from '../types'
import {
    DRAG_TYPE_HEADER_CELL,
    DRAG_TYPE_HEADER_GROUP_CELL,
} from './grid-drag-controller'
import { useGridContext, useGridSelector } from '../context/grid-context'
import {
    GridHeaderCellOverlay,
    GridHeaderGroupCellOverlay,
} from './grid-drag-controller/column/renderer'
import { MAX_COLUMN_GROUP_DEPTH } from '../constants'

const DragOverlayContainer = styled.div`
    background-color: ${theme.backgroundNeutral0};
    ${shadow.regular};
    ${cursor.grabbing};
`

const ChildContainer = styled.div`
    display: flex;
`

const HoverWrap = styled.div`
    background-color: ${theme.backgroundNeutral0Hover};
`

export const GridHeaderDragOverlay = () => {
    const { selectors } = useGridContext()
    const { active } = useDndContext()
    const columnIds = useGridSelector(selectors.selectColumnIds)
    const activeType = active ? active?.data?.current?.type : ''
    const show =
        activeType === DRAG_TYPE_HEADER_GROUP_CELL ||
        activeType === DRAG_TYPE_HEADER_CELL

    const column: Column<any> | null = React.useMemo(
        () => (show ? (active?.data.current?.column as Column<any>) : null),
        [active?.data, show]
    )

    const { groups } = useGridSelector((state) =>
        selectors.selectHeaderHierarchy(state)
    )

    const currentGroup = React.useMemo(
        () =>
            active && activeType === DRAG_TYPE_HEADER_GROUP_CELL
                ? groups.find((g) => g.id === active.id)!
                : null,
        [active, activeType, groups]
    )

    const sortedColumnIds = React.useMemo(
        () =>
            currentGroup
                ? [...currentGroup.columnIds].sort(
                      (a, b) => columnIds.indexOf(a) - columnIds.indexOf(b)
                  )
                : [],
        [columnIds, currentGroup]
    )

    const sortedMiddleLevelIds = React.useMemo(() => {
        if (
            currentGroup?.childIds.length &&
            currentGroup.level === MAX_COLUMN_GROUP_DEPTH
        ) {
            /* Find all children that are groups */
            const childGroups = currentGroup.childIds
                .filter((id) => !currentGroup.columnIds.includes(id))
                .map((id) => groups.find((g) => g.id === id))

            /* This will dedupe the group ids */
            const ids = new Set<string>()
            for (const sortedId of sortedColumnIds) {
                const group = childGroups.find((cg) =>
                    cg?.columnIds.includes(sortedId)
                )
                ids.add(group?.id ?? sortedId)
            }
            return [...ids]
        }

        return null
    }, [sortedColumnIds, currentGroup, groups])

    return column ? (
        <DragOverlayContainer data-testid="pvds-grid-drag-overlay">
            {activeType === DRAG_TYPE_HEADER_CELL ? (
                <HoverWrap>
                    <GridHeaderCellOverlay
                        height={active?.data.current?.height as number}
                        columnId={column.id}
                        isDragging
                        last
                    />
                </HoverWrap>
            ) : currentGroup ? (
                <>
                    <HoverWrap>
                        <GridHeaderGroupCellOverlay
                            height={active?.data.current?.height as number}
                            columnId={column.id}
                            isDragging
                            last
                        />
                    </HoverWrap>
                    {sortedMiddleLevelIds ? (
                        <ChildContainer>
                            {sortedMiddleLevelIds.map((id) =>
                                currentGroup.columnIds.includes(id) ? (
                                    <GridHeaderCellOverlay
                                        columnId={id}
                                        key={id}
                                        spacer
                                        last={
                                            currentGroup.childIds.at(-1) === id
                                        }
                                    />
                                ) : (
                                    <GridHeaderGroupCellOverlay
                                        key={id}
                                        columnId={id}
                                        last={
                                            currentGroup.childIds.at(-1) === id
                                        }
                                    />
                                )
                            )}
                        </ChildContainer>
                    ) : null}
                    <ChildContainer>
                        {sortedColumnIds.map((id) => (
                            <GridHeaderCellOverlay
                                columnId={id}
                                key={id}
                                last={sortedColumnIds.at(-1) === id}
                            />
                        ))}
                    </ChildContainer>
                </>
            ) : null}
        </DragOverlayContainer>
    ) : null
}
