import { Popover, Tooltip } from '@/Components/ui';
import { cn } from '@/lib/cn';
import { type FactorScreenshotGaps, type FormFactor } from '@/types/layout';
import { router } from '@inertiajs/react';
import { Check, ChevronDown } from 'lucide-react';
import type { JSX } from 'react';
import { factorCaption, factorLabel } from './factorLabels';

type FormFactorSwitcherProps = {
    activeFormFactors: FormFactor[];
    activeFactor: FormFactor;
    /** Per-factor screenshot completeness from the editor page props.
     *  Factors with missing frame screenshots get an amber dot so users
     *  discover unfinished devices before exporting empty bezels. */
    screenshotGaps?: FactorScreenshotGaps;
};

function isLandscape(factor: FormFactor): boolean {
    return factor.endsWith('_landscape');
}

/**
 * Compact pill label — primary label from the shared factorLabels module
 * plus a "(L)" suffix on landscape variants so a single row can
 * disambiguate orientations without an icon. The canonical device + pixel
 * dims live in the dropdown's per-row caption.
 */
function pillLabel(factor: FormFactor): string {
    return isLandscape(factor) ? `${factorLabel(factor)} (L)` : factorLabel(factor);
}

function buildFactorUrl(nextFactor: FormFactor): string {
    const params = new URLSearchParams(window.location.search);
    params.set('factor', nextFactor);
    // Preserve `screen` so a factor flip lands on the same screen — without
    // this, the server falls back to `$screens->first()` and bounces the
    // user to Screen 1 every switch.
    return `${window.location.pathname}?${params.toString()}`;
}

export function FormFactorSwitcher({
    activeFormFactors,
    activeFactor,
    screenshotGaps,
}: FormFactorSwitcherProps): JSX.Element | null {
    if (activeFormFactors.length === 0) return null;

    const missingFor = (factor: FormFactor): number =>
        screenshotGaps?.[factor]?.missing ?? 0;
    const anyGaps = activeFormFactors.some((f) => missingFor(f) > 0);

    const pick = (factor: FormFactor) => {
        if (factor === activeFactor) return;
        router.visit(buildFactorUrl(factor), {
            preserveState: false,
            preserveScroll: true,
        });
    };

    return (
        <Popover
            align="end"
            trigger={({ open, toggle }) => (
                <Tooltip label="Switch device" side="bottom">
                    <button
                        type="button"
                        onClick={toggle}
                        data-testid="form-factor-switcher"
                        aria-expanded={open}
                        aria-label="Switch device"
                        className={cn(
                            'inline-flex h-7 items-center gap-1.5 rounded-md border border-border px-2 text-[11px] font-medium transition-colors',
                            open
                                ? 'bg-muted text-foreground'
                                : 'bg-background text-foreground hover:bg-muted/60',
                        )}
                    >
                        <span>{pillLabel(activeFactor)}</span>
                        {anyGaps && (
                            <span
                                className="h-1.5 w-1.5 rounded-full bg-warning"
                                data-testid="form-factor-gaps-dot"
                                aria-hidden="true"
                            />
                        )}
                        <ChevronDown
                            className="h-3 w-3 text-muted-foreground"
                            strokeWidth={2}
                        />
                    </button>
                </Tooltip>
            )}
        >
            <div className="flex min-w-[260px] flex-col gap-0.5">
                {activeFormFactors.map((factor) => {
                    const isActive = factor === activeFactor;
                    return (
                        <button
                            key={factor}
                            type="button"
                            onClick={() => pick(factor)}
                            data-testid={`form-factor-option-${factor}`}
                            data-active={isActive ? 'true' : undefined}
                            className={cn(
                                'flex items-center justify-between gap-3 rounded-md px-2 py-1.5 text-left text-xs transition-colors',
                                isActive
                                    ? 'bg-accent/10 text-accent'
                                    : 'text-foreground hover:bg-muted',
                            )}
                        >
                            <span className="flex min-w-0 flex-col gap-0.5">
                                <span className="flex items-center gap-1.5">
                                    <span className="truncate">
                                        {pillLabel(factor)}
                                    </span>
                                    {missingFor(factor) > 0 && (
                                        <span
                                            className="h-1.5 w-1.5 shrink-0 rounded-full bg-warning"
                                            data-testid={`form-factor-gap-${factor}`}
                                            aria-hidden="true"
                                        />
                                    )}
                                </span>
                                <span className="truncate text-[10px] font-normal text-muted-foreground/80">
                                    {missingFor(factor) > 0
                                        ? `${missingFor(factor)} ${missingFor(factor) === 1 ? 'frame needs a screenshot' : 'frames need screenshots'}`
                                        : factorCaption(factor)}
                                </span>
                            </span>
                            <span className="flex h-4 w-4 items-center justify-center text-muted-foreground">
                                {isActive ? (
                                    <Check
                                        className="h-3.5 w-3.5 text-accent"
                                        strokeWidth={2.5}
                                    />
                                ) : null}
                            </span>
                        </button>
                    );
                })}
            </div>
        </Popover>
    );
}
