import BrandedText from '@/Components/BrandedText';
import ImpersonationBanner from '@/Components/ImpersonationBanner';
import NotificationBell from '@/Components/NotificationBell';
import UserMenu from '@/Components/UserMenu';
import WorkspaceSwitcher, {
    type WorkspacesProp,
} from '@/Components/WorkspaceSwitcher';
import { ThemeToggle, useTheme, useThemeFromPreference } from '@/lib/theme';
import type { SharedProps } from '@/types/inertia';
import UpgradeModal from '@/upgrade/UpgradeModal';
import { useUpgradeModal } from '@/upgrade/useUpgradeModal';
import { Link, router, usePage } from '@inertiajs/react';
import { Activity, Check, ChevronDown, Mail, Menu, Sparkles, Users, X } from 'lucide-react';
import { useEffect, useState } from 'react';

/**
 * Tracks a `min-width` media query. Drives the desktop/mobile nav split: at
 * `< md` the secondary controls (Projects, workspaces, Admin, theme) collapse
 * behind a hamburger so the bar can't overflow a phone width. Rendering by JS
 * (not CSS `hidden`) keeps each control in the DOM exactly once — so the single
 * `WorkspaceSwitcher` never duplicates its test-ids.
 */
function useMinWidth(px: number): boolean {
    const query = `(min-width: ${px}px)`;
    const [matches, setMatches] = useState(() =>
        typeof window !== 'undefined' ? window.matchMedia(query).matches : true,
    );
    useEffect(() => {
        const mq = window.matchMedia(query);
        const onChange = () => setMatches(mq.matches);
        onChange();
        mq.addEventListener('change', onChange);
        return () => mq.removeEventListener('change', onChange);
    }, [query]);
    return matches;
}

function roleLabel(role: string): string {
    return role.charAt(0).toUpperCase() + role.slice(1);
}

/** Owner/Admin = accent (privileged); Editor/Viewer = neutral (mirrors the
 *  desktop WorkspaceSwitcher badge). */
function roleBadgeClasses(role: string): string {
    return role === 'owner' || role === 'admin'
        ? 'border-accent/30 bg-accent/10 text-accent'
        : 'border-border bg-muted text-muted-foreground';
}

export default function AppNav() {
    // App chrome opts into the user's saved theme — paired with
    // useForceLightTheme on marketing / auth / error / checkout surfaces so an
    // Inertia visit from /pricing back to /projects flips dark mode back on.
    useThemeFromPreference();
    const page = usePage<SharedProps & { workspaces: WorkspacesProp }>();
    const { appMode, auth, branding, workspaces } = page.props;
    const [theme] = useTheme();
    const openUpgrade = useUpgradeModal((s) => s.openModal);
    // A higher-tier active plan exists above the workspace's current one (SaaS
    // only — `workspaces` is null in self-hosted, which has no plans).
    const canUpgrade = workspaces?.active.can_upgrade === true;
    const showAdmin = auth.user?.is_admin === true;
    // /admin (dashboard) is saas-only — self_hosted admins land on Settings,
    // which is their actual first stop (mail, branding, signup policy).
    const adminHref = appMode === 'saas' ? '/admin' : '/admin/settings';

    const path = (page.url ?? '').split('?')[0] ?? '';
    const isActive = (prefix: string) =>
        path === prefix || path.startsWith(prefix + '/');

    const isDesktop = useMinWidth(768);
    const [menuOpen, setMenuOpen] = useState(false);
    const closeMenu = () => setMenuOpen(false);
    // Collapse the panel if the viewport grows to desktop while it's open.
    useEffect(() => {
        if (isDesktop) setMenuOpen(false);
    }, [isDesktop]);

    const canManageWs =
        workspaces?.active.role === 'owner' ||
        workspaces?.active.role === 'admin';

    const switchWorkspace = (tenant: number) => {
        closeMenu();
        if (workspaces && tenant === workspaces.active.id) return;
        router.post(
            '/workspace/switch',
            { tenant },
            { preserveScroll: false, preserveState: false },
        );
    };

    // Uniform mobile-menu row.
    const row =
        'flex items-center gap-2.5 rounded-md px-2 py-2 text-[13px] text-foreground transition-colors hover:bg-muted';

    return (
        <>
            <ImpersonationBanner />
            <header className="flex h-14 shrink-0 items-center justify-between gap-2 border-b border-border bg-card px-4 sm:px-6">
                <div className="flex min-w-0 items-center gap-1 sm:gap-6">
                    {/* Mobile: a single menu trigger that ALSO shows the active
                        workspace (name + role) so the bar carries context
                        without opening the panel. Falls back to the brand when
                        there's no workspace (self-hosted). */}
                    {!isDesktop && (
                        <button
                            type="button"
                            onClick={() => setMenuOpen((o) => !o)}
                            aria-label="Menu"
                            aria-expanded={menuOpen}
                            data-testid="appnav-menu-toggle"
                            className="flex h-9 min-w-0 items-center gap-1.5 rounded-md px-1.5 text-foreground transition-colors hover:bg-muted"
                        >
                            {menuOpen ? (
                                <X className="h-5 w-5 shrink-0" strokeWidth={2} />
                            ) : (
                                <Menu className="h-5 w-5 shrink-0" strokeWidth={2} />
                            )}
                            {workspaces ? (
                                <>
                                    <span
                                        className="truncate text-[14px] font-semibold"
                                        data-testid="appnav-active-workspace"
                                    >
                                        {workspaces.active.name}
                                    </span>
                                    <span
                                        className={
                                            'shrink-0 rounded-sm border px-1 text-[9px] font-medium uppercase tracking-wider ' +
                                            roleBadgeClasses(workspaces.active.role)
                                        }
                                    >
                                        {roleLabel(workspaces.active.role)}
                                    </span>
                                    <ChevronDown
                                        className="h-3.5 w-3.5 shrink-0 text-muted-foreground"
                                        strokeWidth={2}
                                    />
                                </>
                            ) : (
                                <span
                                    className="truncate text-[15px] font-semibold tracking-tight"
                                    data-testid="appnav-text-logo"
                                >
                                    <BrandedText
                                        name={branding?.site_name || 'AppShot AI'}
                                    />
                                </span>
                            )}
                        </button>
                    )}
                    {/* Desktop: logo + Projects + the bar switcher widget (which
                        renders only here — mobile uses the flat panel list). */}
                    {isDesktop && (
                        <Link
                            href="/projects"
                            className="mr-1 flex min-w-0 items-center gap-2 truncate text-[15px] font-semibold tracking-tight text-foreground sm:mr-4"
                            aria-label={branding?.site_name ?? 'AppShot AI'}
                        >
                            {branding?.logo_url ? (
                                <img
                                    src={
                                        theme === 'dark'
                                            ? (branding.logo_dark_url ?? branding.logo_url)
                                            : branding.logo_url
                                    }
                                    alt={branding.site_name}
                                    className="h-6 w-auto max-w-[160px] object-contain"
                                    data-testid="appnav-logo"
                                />
                            ) : (
                                <span data-testid="appnav-text-logo">
                                    <BrandedText
                                        name={branding?.site_name || 'AppShot AI'}
                                    />
                                </span>
                            )}
                        </Link>
                    )}
                    {isDesktop && (
                        <NavLink href="/projects" active={isActive('/projects')}>
                            Projects
                        </NavLink>
                    )}
                    {isDesktop && showAdmin && (
                        <NavLink
                            href={adminHref}
                            active={isActive('/admin')}
                            testId="appnav-admin-link"
                        >
                            Admin
                        </NavLink>
                    )}
                    {isDesktop && <WorkspaceSwitcher />}
                </div>
                <div className="flex shrink-0 items-center gap-2">
                    {canUpgrade && (
                        <button
                            type="button"
                            onClick={() => openUpgrade('general')}
                            data-testid="appnav-upgrade"
                            className="inline-flex h-8 items-center gap-1.5 rounded-md border border-accent/30 bg-accent/10 px-2.5 text-[13px] font-medium text-accent transition-colors hover:bg-accent/20"
                        >
                            <Sparkles className="h-3.5 w-3.5" strokeWidth={2} />
                            <span className="hidden sm:inline">Upgrade</span>
                        </button>
                    )}
                    {isDesktop && <ThemeToggle />}
                    {/* SaaS-only in-app notification bell — renders nothing in
                        self-hosted (the `notifications` shared prop is null). */}
                    <NotificationBell />
                    {auth.user && <UserMenu user={auth.user} />}
                </div>
            </header>

            {/* Mobile menu — a flat, uniform list. Only the secondary nav that
                doesn't fit a phone bar; primary controls (logo, bell, avatar)
                stay in the bar. */}
            {!isDesktop && menuOpen && (
                <div
                    className="flex flex-col gap-0.5 border-b border-border bg-card px-3 py-2"
                    data-testid="appnav-mobile-menu"
                >
                    <Link
                        href="/projects"
                        onClick={closeMenu}
                        aria-current={isActive('/projects') ? 'page' : undefined}
                        className={
                            row + (isActive('/projects') ? ' bg-muted' : '')
                        }
                    >
                        Projects
                    </Link>

                    {/* SaaS-only workspace section — switch + manage. */}
                    {workspaces && (
                        <>
                            <div className="px-2 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/70">
                                Workspace
                            </div>
                            {workspaces.memberships.map((m) => {
                                const active = m.id === workspaces.active.id;
                                const caption =
                                    m.personal && m.role === 'owner'
                                        ? `Personal · ${roleLabel(m.role)}`
                                        : roleLabel(m.role);
                                return (
                                    <button
                                        key={m.id}
                                        type="button"
                                        onClick={() => switchWorkspace(m.id)}
                                        data-testid={`appnav-mobile-workspace-${m.id}`}
                                        className={
                                            row +
                                            ' justify-between text-left' +
                                            (active ? ' text-accent' : '')
                                        }
                                    >
                                        <span className="flex min-w-0 flex-col">
                                            <span className="truncate">
                                                {m.name}
                                            </span>
                                            <span className="truncate text-[11px] font-normal text-muted-foreground/80">
                                                {caption}
                                            </span>
                                        </span>
                                        {active && (
                                            <Check
                                                className="h-4 w-4 shrink-0 text-accent"
                                                strokeWidth={2.5}
                                            />
                                        )}
                                    </button>
                                );
                            })}
                            <Link
                                href="/workspace/members"
                                onClick={closeMenu}
                                className={row}
                            >
                                <Users
                                    className="h-4 w-4 text-muted-foreground"
                                    strokeWidth={2}
                                />
                                <span>
                                    {canManageWs ? 'Members' : 'Your membership'}
                                </span>
                            </Link>
                            {canManageWs && (
                                <Link
                                    href="/workspace/activity"
                                    onClick={closeMenu}
                                    className={row}
                                >
                                    <Activity
                                        className="h-4 w-4 text-muted-foreground"
                                        strokeWidth={2}
                                    />
                                    <span>Activity</span>
                                </Link>
                            )}
                            {workspaces.pending_invites_count > 0 && (
                                <Link
                                    href="/workspace/invitations"
                                    onClick={closeMenu}
                                    className={row + ' justify-between text-accent'}
                                >
                                    <span className="flex items-center gap-2.5">
                                        <Mail className="h-4 w-4" strokeWidth={2} />
                                        <span>Pending invitations</span>
                                    </span>
                                    <span className="flex h-4 min-w-4 items-center justify-center rounded-full bg-accent px-1 text-[9px] font-semibold text-accent-foreground">
                                        {workspaces.pending_invites_count}
                                    </span>
                                </Link>
                            )}
                        </>
                    )}

                    {showAdmin && (
                        <Link
                            href={adminHref}
                            onClick={closeMenu}
                            aria-current={isActive('/admin') ? 'page' : undefined}
                            data-testid="appnav-admin-link"
                            className={row}
                        >
                            <span className="text-accent">Admin</span>
                        </Link>
                    )}

                    <div className="mt-1 flex items-center justify-between border-t border-border px-2 pt-2.5">
                        <span className="text-[13px] font-medium text-muted-foreground">
                            Theme
                        </span>
                        <ThemeToggle />
                    </div>
                </div>
            )}
            <UpgradeModal />
        </>
    );
}

function NavLink({
    href,
    active,
    testId,
    children,
}: {
    href: string;
    active: boolean;
    testId?: string;
    children: React.ReactNode;
}) {
    return (
        <Link
            href={href}
            data-testid={testId}
            aria-current={active ? 'page' : undefined}
            className={
                'rounded-md px-2 py-1 text-[13px] font-medium transition-colors ' +
                (active
                    ? 'text-foreground'
                    : 'text-muted-foreground hover:text-foreground')
            }
        >
            {children}
        </Link>
    );
}
