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

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

import {
  Fish,
  Waves,
  Anchor,
  BookOpen,
  ShieldCheck,
  Trophy,
  FileSignature,
  ScrollText,
  ListChecks,
  BookMarked,
  Building2,
  Network,
  SearchCheck,
  Share2,
  PieChart,
  LayoutTemplate,
} 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>) ?? {};
});

const iconClasses = 'w-4';

/**
 * Inject per-account feature module route groups (Fischerei, Meetings, Verband)
 * into the navigation config. These are added as separate collapsible sections
 * before the Administration section (last group).
 *
 * Only modules enabled in the account's settings are shown.
 */
function injectAccountFeatureRoutes(
  config: z.output<typeof NavigationConfigSchema>,
  account: string,
  features: Record<string, boolean>,
): z.output<typeof NavigationConfigSchema> {
  const featureGroups: z.output<typeof NavigationConfigSchema>['routes'] = [];

  if (features.fischerei) {
    featureGroups.push({
      label: 'common:routes.fisheriesManagement',
      collapsible: true,
      children: [
        {
          label: 'common:routes.fisheriesOverview',
          path: `/home/${account}/fischerei`,
          Icon: <Fish className={iconClasses} />,
        },
        {
          label: 'common:routes.fisheriesWaters',
          path: `/home/${account}/fischerei/waters`,
          Icon: <Waves className={iconClasses} />,
        },
        {
          label: 'common:routes.fisheriesLeases',
          path: `/home/${account}/fischerei/leases`,
          Icon: <Anchor className={iconClasses} />,
        },
        {
          label: 'common:routes.fisheriesCatchBooks',
          path: `/home/${account}/fischerei/catch-books`,
          Icon: <BookOpen className={iconClasses} />,
        },
        {
          label: 'common:routes.fisheriesPermits',
          path: `/home/${account}/fischerei/permits`,
          Icon: <ShieldCheck className={iconClasses} />,
        },
        {
          label: 'common:routes.fisheriesCompetitions',
          path: `/home/${account}/fischerei/competitions`,
          Icon: <Trophy className={iconClasses} />,
        },
      ],
    });
  }

  if (features.meetings) {
    featureGroups.push({
      label: 'common:routes.meetingProtocols',
      collapsible: true,
      children: [
        {
          label: 'common:routes.meetingsOverview',
          path: `/home/${account}/meetings`,
          Icon: <BookMarked className={iconClasses} />,
        },
        {
          label: 'common:routes.meetingsProtocols',
          path: `/home/${account}/meetings/protocols`,
          Icon: <ScrollText className={iconClasses} />,
        },
        {
          label: 'common:routes.meetingsTasks',
          path: `/home/${account}/meetings/tasks`,
          Icon: <ListChecks className={iconClasses} />,
        },
      ],
    });
  }

  if (features.verband) {
    featureGroups.push({
      label: 'common:routes.associationManagement',
      collapsible: true,
      children: [
        {
          label: 'common:routes.associationOverview',
          path: `/home/${account}/verband`,
          Icon: <Building2 className={iconClasses} />,
        },
        {
          label: 'common:routes.associationHierarchy',
          path: `/home/${account}/verband/hierarchy`,
          Icon: <Network className={iconClasses} />,
        },
        {
          label: 'common:routes.associationMemberSearch',
          path: `/home/${account}/verband/members`,
          Icon: <SearchCheck className={iconClasses} />,
        },
        {
          label: 'common:routes.associationEvents',
          path: `/home/${account}/verband/events`,
          Icon: <Share2 className={iconClasses} />,
        },
        {
          label: 'common:routes.associationReporting',
          path: `/home/${account}/verband/reporting`,
          Icon: <PieChart className={iconClasses} />,
        },
        {
          label: 'common:routes.associationTemplates',
          path: `/home/${account}/verband/templates`,
          Icon: <LayoutTemplate className={iconClasses} />,
        },
      ],
    });
  }

  if (featureGroups.length === 0) return config;

  // Insert before the last group (Administration)
  const routes = [...config.routes];
  const adminIndex = routes.length - 1;
  routes.splice(adminIndex, 0, ...featureGroups);

  return { ...config, routes };
}

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}
              />
            </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;
