import { redirect } from "next/navigation";

import { auth } from "@/auth";
import { prisma } from "@/lib/db";
import type { ThemeName } from "@/lib/themes";
import type { ProjectDTO } from "@/types/project";
import { SideNavProvider } from "@/components/nav/side-nav-provider";
import { SideNav } from "@/components/nav/side-nav";
import { MobileTopBar } from "@/components/nav/mobile-top-bar";
import { ProjectsProvider } from "@/components/projects/projects-context";
import { ScheduledPanelProvider } from "@/components/scheduled/scheduled-panel-provider";
import { ScheduledPanel } from "@/components/scheduled/scheduled-panel";
import { BoardViewProvider } from "@/components/board/board-view-provider";
import { HoldOnCompleteProvider } from "@/components/hold-on-complete";

export default async function AppLayout({ children }: { children: React.ReactNode }) {
  const session = await auth();
  // Defense in depth: proxy.ts already redirects unauthenticated requests,
  // but every protected data boundary should check for itself too.
  if (!session?.user) redirect("/login");

  // Just the list for the sidebar/`/projects` page -- each project's own
  // board (categories/groups/todos) is fetched separately by its own page.
  // `theme` is stored as free text; the set of valid names is enforced
  // client-side (ProjectThemeSchema) so a plain assertion is safe here.
  const [projects, profile] = await Promise.all([
    prisma.project.findMany({
      where: { ownerId: session.user.id },
      orderBy: { createdAt: "asc" },
      select: { id: true, title: true, theme: true },
    }),
    // The user's profile for the sidebar's bottom user block (name + photo,
    // both optional); the /profile page fetches the same row itself.
    prisma.user.findUnique({
      where: { id: session.user.id },
      select: { firstName: true, lastName: true, avatar: true },
    }),
  ]);

  const projectList: ProjectDTO[] = projects.map((p) => ({
    id: p.id,
    title: p.title,
    theme: p.theme as ThemeName | null,
  }));

  const userName =
    [profile?.firstName, profile?.lastName]
      .filter((part): part is string => Boolean(part && part.trim()))
      .map((part) => part.trim())
      .join(" ") || null;

  return (
    <SideNavProvider>
      <ScheduledPanelProvider>
        <ProjectsProvider initialProjects={projectList}>
          <BoardViewProvider>
            <HoldOnCompleteProvider>
            {/* Responsive shell:
                - md and up: the original three-column desktop layout, with
                  the same min-width + horizontal-scroll fallback as before.
                - below md (phones): a true stacked app layout -- top bar,
                  full-height board, and the Scheduled dock (rendered inside
                  ScheduledPanel) take the full column with no horizontal
                  scrolling; h-dvh tracks the mobile browser's dynamic
                  toolbar instead of the stale 100vh. */}
            <div className="flex h-dvh flex-col md:h-screen md:min-w-[860px] md:flex-row md:overflow-x-auto">
              <MobileTopBar />
              <SideNav
                userEmail={session.user.email ?? ""}
                userName={userName}
                avatar={profile?.avatar ?? null}
                role={session.user.role}
              />
              <main className="min-h-0 flex-1 overflow-auto">{children}</main>
              <ScheduledPanel />
            </div>
            </HoldOnCompleteProvider>
          </BoardViewProvider>
        </ProjectsProvider>
      </ScheduledPanelProvider>
    </SideNavProvider>
  );
}
