import AppNav from '@/Components/AppNav';
import { Button, Card } from '@/Components/ui';
import { cn } from '@/lib/cn';
import { Head, router } from '@inertiajs/react';
import {
    Bell,
    Check,
    FilePlus2,
    FolderMinus,
    FolderPlus,
    Mail,
    ShieldCheck,
    Trash2,
    type LucideIcon,
} from 'lucide-react';

/**
 * Full notification history (Team Workspaces Δ25) — the bell's "View all"
 * page. All notifications, newest-first, unread highlighted, paginated. The
 * paginated list is the `feed` prop (the `notifications` shared prop is the
 * bell's latest-10 and stays separate).
 */
type NotificationItem = {
    id: string;
    title: string;
    body: string;
    url: string | null;
    workspace: string | null;
    category: string | null;
    read_at: string | null;
    created_at: string;
};

type Paginated<T> = {
    data: T[];
    current_page: number;
    last_page: number;
    total: number;
    links: Array<{ url: string | null; label: string; active: boolean }>;
};

type Props = {
    feed: Paginated<NotificationItem>;
    unread_count: number;
    filters: { type: string };
};

const TYPE_TABS: Array<{ key: string; label: string }> = [
    { key: 'all', label: 'All' },
    { key: 'projects', label: 'Projects' },
    { key: 'members', label: 'Members' },
    { key: 'invites', label: 'Invites' },
];

// Category → icon + tone (mirrors the activity log's visual language).
function iconFor(category: string | null): { Icon: LucideIcon; tone: string } {
    switch (category) {
        case 'project.created':
            return { Icon: FilePlus2, tone: 'text-success' };
        case 'project.deleted':
            return { Icon: Trash2, tone: 'text-destructive' };
        case 'project.shared':
            return { Icon: FolderPlus, tone: 'text-success' };
        case 'project.revoked':
            return { Icon: FolderMinus, tone: 'text-destructive' };
        case 'role':
            return { Icon: ShieldCheck, tone: 'text-accent' };
        case 'invite':
            return { Icon: Mail, tone: 'text-accent' };
        default:
            return { Icon: Bell, tone: 'text-muted-foreground' };
    }
}

const RELATIVE_FMT = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });

function relativeTime(iso: string): string {
    const ms = new Date(iso).getTime();
    if (Number.isNaN(ms)) return '';
    const diffMs = ms - Date.now();
    const absMin = Math.abs(diffMs) / 60_000;
    if (absMin < 1) return 'just now';
    if (absMin < 60) return RELATIVE_FMT.format(Math.round(diffMs / 60_000), 'minute');
    if (absMin < 60 * 24)
        return RELATIVE_FMT.format(Math.round(diffMs / 3_600_000), 'hour');
    if (absMin < 60 * 24 * 30)
        return RELATIVE_FMT.format(Math.round(diffMs / 86_400_000), 'day');
    return RELATIVE_FMT.format(Math.round(diffMs / (86_400_000 * 30)), 'month');
}

// Mark-read via plain fetch (NOT Inertia router) so it never races a navigating
// visit — same rule as the bell. Then refresh the list + bell prop.
function postRead(url: string): Promise<unknown> {
    const csrf =
        document
            .querySelector('meta[name="csrf-token"]')
            ?.getAttribute('content') ?? '';
    return fetch(url, {
        method: 'POST',
        credentials: 'same-origin',
        keepalive: true,
        headers: { 'X-CSRF-TOKEN': csrf, Accept: 'application/json' },
    }).catch(() => undefined);
}

export default function NotificationsIndex({
    feed,
    unread_count,
    filters,
}: Props) {
    const refresh = () =>
        router.reload({ only: ['feed', 'unread_count', 'notifications'] });

    const applyType = (type: string) =>
        router.get(
            '/notifications',
            type !== 'all' ? { type } : {},
            { preserveScroll: true, preserveState: true },
        );

    const markRead = async (id: string) => {
        await postRead(`/notifications/${id}/read`);
        refresh();
    };

    const markAllRead = async () => {
        await postRead('/notifications/read-all');
        refresh();
    };

    const openItem = (item: NotificationItem) => {
        if (!item.read_at) void postRead(`/notifications/${item.id}/read`);
        if (item.url) router.visit(item.url);
    };

    return (
        <>
            <Head title="Notifications" />
            <div className="flex min-h-screen flex-col bg-background text-foreground">
                <AppNav />
                <main className="mx-auto w-full max-w-2xl flex-1 px-6 py-8">
                    <div className="flex items-center justify-between gap-3">
                        <div>
                            <h1 className="text-xl font-semibold tracking-tight">
                                Notifications
                            </h1>
                            <p className="mt-1 text-[12px] text-muted-foreground">
                                {unread_count > 0
                                    ? `${unread_count} unread`
                                    : "You're all caught up."}
                            </p>
                        </div>
                        {unread_count > 0 && (
                            <Button
                                variant="secondary"
                                size="md"
                                onClick={markAllRead}
                                data-testid="notifications-mark-all-read"
                            >
                                <Check className="h-4 w-4" strokeWidth={2.5} />
                                Mark all read
                            </Button>
                        )}
                    </div>

                    {/* Type filter tabs (mirrors the activity page). */}
                    <div
                        className="mt-5 flex flex-wrap gap-1"
                        data-testid="notifications-type-tabs"
                    >
                        {TYPE_TABS.map((tab) => {
                            const active = filters.type === tab.key;
                            return (
                                <button
                                    key={tab.key}
                                    type="button"
                                    onClick={() => applyType(tab.key)}
                                    data-testid={`notifications-type-${tab.key}`}
                                    className={cn(
                                        'rounded-md border px-2.5 py-1 text-[12px] font-medium transition-colors',
                                        active
                                            ? 'border-accent/40 bg-accent/10 text-accent'
                                            : 'border-border text-muted-foreground hover:bg-muted hover:text-foreground',
                                    )}
                                >
                                    {tab.label}
                                </button>
                            );
                        })}
                    </div>

                    <Card padding="none" className="mt-4 overflow-hidden">
                        {feed.data.length === 0 ? (
                            <div
                                className="flex flex-col items-center gap-2 px-6 py-16 text-center"
                                data-testid="notifications-empty"
                            >
                                <Bell
                                    className="h-6 w-6 text-muted-foreground/50"
                                    strokeWidth={1.5}
                                />
                                <p className="text-[12px] text-muted-foreground">
                                    {filters.type !== 'all'
                                        ? 'No notifications match this filter.'
                                        : 'No notifications yet.'}
                                </p>
                            </div>
                        ) : (
                            <ul className="divide-y divide-border">
                                {feed.data.map((item) => {
                                    const unread = !item.read_at;
                                    const clickable = Boolean(item.url);
                                    const { Icon, tone } = iconFor(item.category);
                                    return (
                                        <li key={item.id}>
                                            <div
                                                role={clickable ? 'button' : undefined}
                                                tabIndex={clickable ? 0 : undefined}
                                                onClick={
                                                    clickable
                                                        ? () => openItem(item)
                                                        : undefined
                                                }
                                                data-testid={`notification-row-${item.id}`}
                                                data-unread={unread ? 'true' : undefined}
                                                className={cn(
                                                    'flex items-start gap-3 px-4 py-3 transition-colors',
                                                    clickable &&
                                                        'cursor-pointer hover:bg-muted',
                                                    unread && 'bg-accent/[0.06]',
                                                )}
                                            >
                                                <span className="relative mt-0.5 shrink-0">
                                                    <Icon
                                                        className={cn('h-4 w-4', tone)}
                                                        strokeWidth={2}
                                                    />
                                                    {unread && (
                                                        <span
                                                            className="absolute -right-1 -top-1 h-1.5 w-1.5 rounded-full bg-accent"
                                                            aria-hidden
                                                        />
                                                    )}
                                                </span>
                                                <div className="min-w-0 flex-1">
                                                    <p
                                                        className={cn(
                                                            'text-[13px]',
                                                            unread
                                                                ? 'font-medium text-foreground'
                                                                : 'text-foreground/90',
                                                        )}
                                                    >
                                                        {item.title}
                                                    </p>
                                                    {item.body && (
                                                        <p className="mt-0.5 text-[12px] leading-snug text-muted-foreground">
                                                            {item.body}
                                                        </p>
                                                    )}
                                                    <p className="mt-1 flex flex-wrap items-center gap-1.5 text-[11px] text-muted-foreground/70">
                                                        {item.workspace && (
                                                            <span className="rounded-sm border border-border bg-muted px-1 text-[10px] font-medium text-muted-foreground">
                                                                {item.workspace}
                                                            </span>
                                                        )}
                                                        <span>
                                                            {relativeTime(item.created_at)}
                                                        </span>
                                                    </p>
                                                </div>
                                                {unread && (
                                                    <button
                                                        type="button"
                                                        onClick={(e) => {
                                                            e.stopPropagation();
                                                            void markRead(item.id);
                                                        }}
                                                        data-testid={`notification-mark-read-${item.id}`}
                                                        className="shrink-0 rounded-sm px-1.5 py-0.5 text-[11px] font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
                                                    >
                                                        Mark read
                                                    </button>
                                                )}
                                            </div>
                                        </li>
                                    );
                                })}
                            </ul>
                        )}
                    </Card>

                    {feed.last_page > 1 && (
                        <nav className="mt-4 flex items-center justify-between">
                            <span className="text-[11px] text-muted-foreground">
                                Page {feed.current_page} of {feed.last_page} ·{' '}
                                {feed.total} total
                            </span>
                            <div className="flex flex-wrap gap-1">
                                {feed.links.map((link, i) => (
                                    <button
                                        key={`${link.label}-${i}`}
                                        type="button"
                                        disabled={!link.url}
                                        onClick={() =>
                                            link.url && router.visit(link.url)
                                        }
                                        className={cn(
                                            'rounded-md border border-border px-2.5 py-1 text-[11px] font-medium transition-colors disabled:opacity-40',
                                            link.active
                                                ? 'border-accent/40 bg-accent/5 text-accent'
                                                : 'text-muted-foreground hover:bg-muted hover:text-foreground',
                                        )}
                                        dangerouslySetInnerHTML={{ __html: link.label }}
                                    />
                                ))}
                            </div>
                        </nav>
                    )}
                </main>
            </div>
        </>
    );
}
