import { X } from 'lucide-react';
import { useEffect, useRef } from 'react';
import { Button } from '@/components/ui/button';
import { TOUR_POPOVER_WIDTH } from '@/lib/application-tour/constants';
import {
    computePopoverPosition
    
    
} from '@/lib/application-tour/position';
import type {PopoverPlacement, TargetRect} from '@/lib/application-tour/position';
import type { TourStep } from '@/lib/application-tour/steps';
import { cn } from '@/lib/utils';

type TourStepPopoverProps = {
    currentStep: TourStep;
    isLastStep: boolean;
    isPreparingStep: boolean;
    onBack: () => void;
    onNext: () => void;
    onSkip: () => void;
    rect: TargetRect | null;
    stepIndex: number;
    totalSteps: number;
};

const placementArrowClass: Record<PopoverPlacement, string> = {
    top: 'bottom-0 left-1/2 -translate-x-1/2 translate-y-full border-x-8 border-t-8 border-x-transparent border-t-background',
    bottom: 'top-0 left-1/2 -translate-x-1/2 -translate-y-full border-x-8 border-b-8 border-x-transparent border-b-background',
    left: 'top-1/2 right-0 translate-x-full -translate-y-1/2 border-y-8 border-l-8 border-y-transparent border-l-background',
    right: 'top-1/2 left-0 -translate-x-full -translate-y-1/2 border-y-8 border-r-8 border-y-transparent border-r-background',
};

function getFocusableElements(container: HTMLElement): HTMLElement[] {
    return Array.from(
        container.querySelectorAll<HTMLElement>(
            'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])',
        ),
    ).filter((element) => !element.hasAttribute('disabled'));
}

export function TourStepPopover({
    currentStep,
    isLastStep,
    isPreparingStep,
    onBack,
    onNext,
    onSkip,
    rect,
    stepIndex,
    totalSteps,
}: TourStepPopoverProps) {
    const dialogRef = useRef<HTMLDivElement>(null);
    const StepIcon = currentStep.icon;

    const position = rect
        ? computePopoverPosition(rect, currentStep.placement ?? 'auto')
        : {
              top: window.innerHeight / 2 - 120,
              left: window.innerWidth / 2 - TOUR_POPOVER_WIDTH / 2,
              placement: 'bottom' as PopoverPlacement,
          };

    useEffect(() => {
        dialogRef.current?.focus();
    }, [currentStep.id]);

    useEffect(() => {
        const container = dialogRef.current;

        if (!container) {
            return;
        }

        const handleKeyDown = (event: KeyboardEvent) => {
            if (event.key !== 'Tab') {
                return;
            }

            const focusable = getFocusableElements(container);

            if (focusable.length === 0) {
                return;
            }

            const first = focusable[0];
            const last = focusable[focusable.length - 1];

            if (event.shiftKey && document.activeElement === first) {
                event.preventDefault();
                last.focus();
            } else if (!event.shiftKey && document.activeElement === last) {
                event.preventDefault();
                first.focus();
            }
        };

        container.addEventListener('keydown', handleKeyDown);

        return () => container.removeEventListener('keydown', handleKeyDown);
    }, []);

    const progress = ((stepIndex + 1) / totalSteps) * 100;

    return (
        <div
            className={cn(
                'fixed z-[70] w-[min(20rem,calc(100vw-2rem))] rounded-xl border bg-background p-5 text-foreground shadow-2xl motion-reduce:animate-none sm:w-80',
                'animate-in fade-in-0 zoom-in-95 duration-200',
                rect && 'slide-in-from-bottom-2',
            )}
            style={{
                top: position.top,
                left: position.left,
                width: TOUR_POPOVER_WIDTH,
            }}
            role="dialog"
            aria-modal="true"
            tabIndex={-1}
            ref={dialogRef}
            aria-labelledby="application-tour-title"
            aria-describedby="application-tour-description"
        >
            {rect && (
                <span
                    className={cn(
                        'absolute size-0',
                        placementArrowClass[position.placement],
                    )}
                    aria-hidden="true"
                />
            )}

            <Button
                type="button"
                variant="ghost"
                size="icon"
                className="absolute top-2 right-2"
                onClick={onSkip}
                aria-label="Skip application tour"
            >
                <X />
            </Button>

            <div className="mb-3 h-1 overflow-hidden rounded-full bg-muted">
                <div
                    className="h-full rounded-full bg-primary transition-all duration-300 ease-out motion-reduce:transition-none"
                    style={{ width: `${progress}%` }}
                />
            </div>

            <div
                className="flex items-center gap-2"
                aria-live="polite"
                aria-atomic="true"
            >
                <div className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary">
                    <StepIcon className="size-4" />
                </div>
                <p className="text-xs font-medium text-muted-foreground">
                    Step {stepIndex + 1} of {totalSteps}
                </p>
            </div>

            <div className="mt-3 flex justify-center gap-1.5">
                {Array.from({ length: totalSteps }).map((_, index) => (
                    <span
                        key={index}
                        className={cn(
                            'h-1.5 rounded-full transition-all duration-300 motion-reduce:transition-none',
                            index === stepIndex
                                ? 'w-5 bg-primary'
                                : 'w-1.5 bg-muted-foreground/30',
                        )}
                        aria-hidden="true"
                    />
                ))}
            </div>

            <h2
                id="application-tour-title"
                className="mt-3 text-base font-semibold"
                key={`title-${currentStep.id}`}
            >
                {currentStep.title}
            </h2>
            <p
                id="application-tour-description"
                className="mt-2 text-sm leading-relaxed text-muted-foreground"
                key={`description-${currentStep.id}`}
            >
                {currentStep.description}
            </p>

            <div className="mt-4 flex items-center justify-between gap-2">
                <Button type="button" variant="ghost" size="sm" onClick={onSkip}>
                    Skip tour
                </Button>
                <div className="flex gap-2">
                    {stepIndex > 0 && (
                        <Button
                            type="button"
                            variant="outline"
                            size="sm"
                            onClick={onBack}
                            disabled={isPreparingStep}
                        >
                            Back
                        </Button>
                    )}
                    <Button
                        type="button"
                        size="sm"
                        onClick={onNext}
                        disabled={isPreparingStep}
                    >
                        {isLastStep ? 'Finish' : 'Next'}
                    </Button>
                </div>
            </div>
        </div>
    );
}
