import { cache } from 'react';
import { use } from 'react';

import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';

import { Fish, FileSignature, Building2 } from 'lucide-react';
import * as z from 'zod';

import { getSupabaseServerClient } from '@kit/supabase/server-client';
import { TeamAccountWorkspaceContextProvider } from '@kit/team-accounts/components';
import { NavigationConfigSchema } from '@kit/ui/navigation-schema';
import { Page, PageMobileNavigation, PageNavigation } from '@kit/ui/page';
import { SidebarProvider } from '@kit/ui/sidebar';

import { AppLogo } from '~/components/app-logo';
import { getTeamAccountSidebarConfig } from '~/config/team-account-navigation.config';

// local imports
import { TeamAccountLayoutMobileNavigation } from './_components/team-account-layout-mobile-navigation';
import { TeamAccountLayoutSidebar } from './_components/team-account-layout-sidebar';
import { TeamAccountNavigationMenu } from './_components/team-account-navigation-menu';
import { loadTeamWorkspace } from './_lib/server/team-account-workspace.loader';

type TeamWorkspaceLayoutProps = React.PropsWithChildren<{
  params: Promise<{ account: string }>;
}>;

function TeamWorkspaceLayout({ children, params }: TeamWorkspaceLayoutProps) {
  const account = use(params).account;
  const state = use(getLayoutState(account));

  if (state.style === 'sidebar') {
    return <SidebarLayout account={account}>{children}</SidebarLayout>;
  }

  return <HeaderLayout account={account}>{children}</HeaderLayout>;
}

/**
 * Query account_settings.features for a given account slug.
 * Cached per-request so multiple calls don't hit the DB twice.
 */
const getAccountFeatures = cache(async (accountSlug: string) => {
  const client = getSupabaseServerClient();

  const { data: accountData } = await client
    .from('accounts')
    .select('id')
    .eq('slug', accountSlug)
    .single();

  if (!accountData) return {};

  const { data: settings } = await client
    .from('account_settings')
    .select('features')
    .eq('account_id', accountData.id)
    .maybeSingle();

  return (settings?.features as Record<string, boolean>) ?? {};
});

/**
 * Inject per-account feature routes (e.g. Fischerei) into the parsed
 * navigation config. The entry is inserted right after "Veranstaltungen".
 */
function injectAccountFeatureRoutes(
  config: z.output<typeof NavigationConfigSchema>,
  account: string,
  features: Record<string, boolean>,
): z.output<typeof NavigationConfigSchema> {
  if (!features.fischerei && !features.meetings && !features.verband)
    return config;

  const featureEntries: Array<{
    label: string;
    path: string;
    Icon: React.ReactNode;
  }> = [];

  if (features.fischerei) {
    featureEntries.push({
      label: 'common.routes.fischerei',
      path: `/home/${account}/fischerei`,
      Icon: <Fish className="w-4" />,
    });
  }

  if (features.meetings) {
    featureEntries.push({
      label: 'common.routes.meetings',
      path: `/home/${account}/meetings`,
      Icon: <FileSignature className="w-4" />,
    });
  }

  if (features.verband) {
    featureEntries.push({
      label: 'common.routes.verband',
      path: `/home/${account}/verband`,
      Icon: <Building2 className="w-4" />,
    });
  }

  return {
    ...config,
    routes: config.routes.map((group) => {
      if (!('children' in group)) return group;

      const eventsIndex = group.children.findIndex(
        (child) => child.label === 'common.routes.events',
      );

      if (eventsIndex === -1) return group;

      const newChildren = [...group.children];
      newChildren.splice(eventsIndex + 1, 0, ...featureEntries);

      return { ...group, children: newChildren };
    }),
  };
}

async function SidebarLayout({
  account,
  children,
}: React.PropsWithChildren<{
  account: string;
}>) {
  const [data, state, features] = await Promise.all([
    loadTeamWorkspace(account),
    getLayoutState(account),
    getAccountFeatures(account),
  ]);

  if (!data) {
    redirect('/');
  }

  const baseConfig = getTeamAccountSidebarConfig(account);
  const config = injectAccountFeatureRoutes(baseConfig, account, features);

  const accounts = data.accounts.map(({ name, slug, picture_url }) => ({
    label: name,
    value: slug,
    image: picture_url,
  }));

  return (
    <TeamAccountWorkspaceContextProvider value={data}>
      <SidebarProvider defaultOpen={state.open}>
        <Page style={'sidebar'}>
          <PageNavigation>
            <TeamAccountLayoutSidebar
              account={account}
              accountId={data.account.id}
              accounts={accounts}
              user={data.user}
              config={config}
            />
          </PageNavigation>

          <PageMobileNavigation>
            <AppLogo />

            <div className={'flex'}>
              <TeamAccountLayoutMobileNavigation
                userId={data.user.id}
                accounts={accounts}
                account={account}
                config={config}
              />
            </div>
          </PageMobileNavigation>

          {children}
        </Page>
      </SidebarProvider>
    </TeamAccountWorkspaceContextProvider>
  );
}

async function HeaderLayout({
  account,
  children,
}: React.PropsWithChildren<{
  account: string;
}>) {
  const [data, features] = await Promise.all([
    loadTeamWorkspace(account),
    getAccountFeatures(account),
  ]);

  const baseConfig = getTeamAccountSidebarConfig(account);
  const config = injectAccountFeatureRoutes(baseConfig, account, features);

  const accounts = data.accounts.map(({ name, slug, picture_url }) => ({
    label: name,
    value: slug,
    image: picture_url,
  }));

  return (
    <TeamAccountWorkspaceContextProvider value={data}>
      <Page style={'header'}>
        <PageNavigation>
          <TeamAccountNavigationMenu workspace={data} config={config} />
        </PageNavigation>

        <PageMobileNavigation className={'flex items-center justify-between'}>
          <div>
            <AppLogo />
          </div>

          <div>
            <TeamAccountLayoutMobileNavigation
              userId={data.user.id}
              accounts={accounts}
              account={account}
            />
          </div>
        </PageMobileNavigation>

        {children}
      </Page>
    </TeamAccountWorkspaceContextProvider>
  );
}

async function getLayoutState(account: string) {
  const cookieStore = await cookies();
  const config = getTeamAccountSidebarConfig(account);

  const LayoutStyleSchema = z
    .enum(['sidebar', 'header', 'custom'])
    .default(config.style);

  const sidebarOpenCookie = cookieStore.get('sidebar_state');
  const layoutCookie = cookieStore.get('layout-style');

  const layoutStyle = LayoutStyleSchema.safeParse(layoutCookie?.value);

  const sidebarOpenCookieValue = sidebarOpenCookie
    ? sidebarOpenCookie.value === 'true'
    : !config.sidebarCollapsed;

  const style = layoutStyle.success ? layoutStyle.data : config.style;

  return {
    open: sidebarOpenCookieValue,
    style,
  };
}

export default TeamWorkspaceLayout;
