import { Link } from '@inertiajs/react';
import { Search, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Input } from '@/components/ui/input';
import type { Paginated } from '@/types';

/**
 * The frame around a list: search, filters and the actions that belong to the
 * whole page. Kept as one strip so filter state is obvious at a glance.
 */
export function FilterBar({
    children,
    actions,
    className,
}: {
    children: React.ReactNode;
    actions?: React.ReactNode;
    className?: string;
}) {
    return (
        <div
            className={cn(
                'bg-card shadow-card flex flex-col gap-3 rounded-xl px-4 py-3 ring-1 ring-hairline lg:flex-row lg:items-center lg:gap-4',
                className,
            )}
        >
            <div className="flex flex-1 flex-wrap items-center gap-2 sm:gap-3">
                {children}
            </div>
            {actions ? (
                <div className="flex shrink-0 items-center gap-2">{actions}</div>
            ) : null}
        </div>
    );
}

export function FilterField({
    label,
    children,
    className,
}: {
    label: string;
    children: React.ReactNode;
    className?: string;
}) {
    return (
        <label className={cn('flex min-w-0 flex-col gap-1', className)}>
            <span className="crm-label">{label}</span>
            {children}
        </label>
    );
}

export function SearchInput({
    value,
    onChange,
    placeholder = 'Search',
    className,
}: {
    value: string;
    onChange: (value: string) => void;
    placeholder?: string;
    className?: string;
}) {
    return (
        <div className={cn('relative min-w-[12rem] flex-1', className)}>
            <Search
                aria-hidden
                className="text-muted-foreground pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2"
            />
            <Input
                value={value}
                onChange={(event) => onChange(event.target.value)}
                placeholder={placeholder}
                className="h-9 pl-8"
            />
            {value ? (
                <button
                    type="button"
                    onClick={() => onChange('')}
                    aria-label="Clear search"
                    className="text-muted-foreground hover:text-foreground absolute top-1/2 right-2 -translate-y-1/2 rounded p-0.5"
                >
                    <X className="size-3.5" />
                </button>
            ) : null}
        </div>
    );
}

/**
 * A small set of mutually exclusive views, for example Active / All / Stalled.
 * Quieter than tabs and it fits beside filters.
 */
export function SegmentedControl<T extends string>({
    options,
    value,
    onChange,
    className,
}: {
    options: Array<{ value: T; label: string; count?: number }>;
    value: T;
    onChange: (value: T) => void;
    className?: string;
}) {
    return (
        <div
            role="tablist"
            className={cn(
                'bg-muted/60 inline-flex items-center gap-0.5 rounded-lg p-0.5',
                className,
            )}
        >
            {options.map((option) => {
                const isActive = option.value === value;

                return (
                    <button
                        key={option.value}
                        role="tab"
                        type="button"
                        aria-selected={isActive}
                        onClick={() => onChange(option.value)}
                        className={cn(
                            'rounded-md px-2.5 py-1 text-xs font-medium whitespace-nowrap transition-colors',
                            isActive
                                ? 'bg-card shadow-card text-foreground ring-1 ring-hairline'
                                : 'text-muted-foreground hover:text-foreground',
                        )}
                    >
                        {option.label}
                        {option.count !== undefined ? (
                            <span className="crm-num ml-1 opacity-60">
                                {option.count}
                            </span>
                        ) : null}
                    </button>
                );
            })}
        </div>
    );
}

/**
 * Applied filters as removable chips, so it is always clear why a list is
 * showing what it is showing.
 */
export function ActiveFilters({
    filters,
    onClear,
    className,
}: {
    filters: Array<{ key: string; label: string; value: string; onRemove: () => void }>;
    onClear: () => void;
    className?: string;
}) {
    if (filters.length === 0) {
        return null;
    }

    return (
        <div className={cn('flex flex-wrap items-center gap-1.5', className)}>
            <span className="crm-label">Filtered by</span>
            {filters.map((filter) => (
                <button
                    key={filter.key}
                    type="button"
                    onClick={filter.onRemove}
                    className="bg-accent text-accent-foreground hover:ring-foreground/20 group inline-flex items-center gap-1.5 rounded-md px-2 py-0.5 text-xs font-medium ring-1 ring-inset ring-transparent"
                >
                    <span className="text-muted-foreground">{filter.label}</span>
                    {filter.value}
                    <X className="size-3 opacity-60 group-hover:opacity-100" />
                </button>
            ))}
            <button
                type="button"
                onClick={onClear}
                className="text-muted-foreground hover:text-foreground ml-1 text-xs underline-offset-2 hover:underline"
            >
                Clear all
            </button>
        </div>
    );
}

/**
 * The card a table lives in, so every list page frames its data the same way.
 */
export function TableCard({
    children,
    className,
}: {
    children: React.ReactNode;
    className?: string;
}) {
    return (
        <div
            className={cn(
                'bg-card shadow-card crm-scroll overflow-hidden rounded-xl ring-1 ring-hairline',
                className,
            )}
        >
            {children}
        </div>
    );
}

/**
 * The footer under a paginated table. Falls back to a count when there is only
 * one page, because a lone "1" in a pager is noise.
 */
export function DataPagination({
    page,
    noun,
    className,
}: {
    page: Paginated<unknown>;
    noun: string;
    className?: string;
}) {
    const summary = `Showing ${page.from ?? 0} to ${page.to ?? 0} of ${page.total} ${noun}`;

    if (page.last_page <= 1) {
        return (
            <div
                className={cn(
                    'text-muted-foreground border-hairline border-t px-4 py-2.5 text-xs',
                    className,
                )}
            >
                {summary}
            </div>
        );
    }

    return (
        <div
            className={cn(
                'border-hairline flex flex-wrap items-center justify-between gap-3 border-t px-4 py-2.5',
                className,
            )}
        >
            <p className="text-muted-foreground text-xs">{summary}</p>
            <div className="flex flex-wrap items-center gap-1">
                {page.links.map((link, index) =>
                    link.url ? (
                        <Link
                            key={`${link.label}-${index}`}
                            href={link.url}
                            preserveScroll
                            className={cn(
                                'rounded-md px-2.5 py-1 text-xs ring-1 ring-inset transition-colors',
                                link.active
                                    ? 'bg-primary text-primary-foreground ring-transparent'
                                    : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground ring-hairline',
                            )}
                            dangerouslySetInnerHTML={{ __html: link.label }}
                        />
                    ) : (
                        <span
                            key={`${link.label}-${index}`}
                            className="text-muted-foreground/50 ring-hairline rounded-md px-2.5 py-1 text-xs ring-1 ring-inset"
                            dangerouslySetInnerHTML={{ __html: link.label }}
                        />
                    ),
                )}
            </div>
        </div>
    );
}
