import { A, useLocation, useNavigate, useSearchParams } from '@solidjs/router';
import { For, createEffect, createMemo, createSignal, onCleanup, onMount, type JSX } from 'solid-js';
import AdminSidebar from './AdminSidebar';
import { isExternalIdentity } from '~/lib/admin-auth';
import { clearAdminSession, hasAdminSession, setAdminSession } from '~/lib/admin-session';

type Tab = { href: string; label: string; exact?: boolean };

const TAB_SETS: Array<{ prefixes: string[]; tabs: Tab[] }> = [
  {
    prefixes: ['/admin/roles'],
    tabs: [
      { href: '/admin/roles', label: 'Roles', exact: true },
      { href: '/admin/roles/create', label: 'Create Role' },
      { href: '/admin/roles/templates', label: 'View Roles' },
    ],
  },
  {
    prefixes: ['/admin/runtime-roles'],
    tabs: [
      { href: '/admin/runtime-roles', label: 'Roles', exact: true },
      { href: '/admin/runtime-roles/new', label: 'Create Role' },
      { href: '/admin/role-ui-configs', label: 'View Roles' },
    ],
  },
];

function IconBell() {
  return (
    <svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9">
      <path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9" />
      <path d="M13.73 21a2 2 0 0 1-3.46 0" />
    </svg>
  );
}

function IconSearch() {
  return (
    <svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
      <circle cx="11" cy="11" r="7.5" />
      <path d="m20 20-3.8-3.8" />
    </svg>
  );
}

function IconHelp() {
  return (
    <svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <circle cx="12" cy="12" r="9" />
      <path d="M9.3 9a2.8 2.8 0 1 1 4.9 2c-.8.9-1.7 1.4-1.7 2.5" />
      <path d="M12 17h.01" />
    </svg>
  );
}

function IconCog() {
  return (
    <svg class="h-5 w-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
      <path d="M12 15.5A3.5 3.5 0 1 0 12 8.5a3.5 3.5 0 0 0 0 7Z" />
      <path d="M19.4 15a1.6 1.6 0 0 0 .3 1.7l.1.1a2 2 0 0 1-2.8 2.8l-.1-.1a1.6 1.6 0 0 0-1.7-.3 1.6 1.6 0 0 0-1 1.5V21a2 2 0 0 1-4 0v-.2a1.6 1.6 0 0 0-1-1.5 1.6 1.6 0 0 0-1.7.3l-.1.1a2 2 0 0 1-2.8-2.8l.1-.1a1.6 1.6 0 0 0 .3-1.7 1.6 1.6 0 0 0-1.5-1H3a2 2 0 0 1 0-4h.2a1.6 1.6 0 0 0 1.5-1 1.6 1.6 0 0 0-.3-1.7l-.1-.1a2 2 0 0 1 2.8-2.8l.1.1a1.6 1.6 0 0 0 1.7.3h.1a1.6 1.6 0 0 0 .9-1.5V3a2 2 0 1 1 4 0v.2a1.6 1.6 0 0 0 .9 1.5h.1a1.6 1.6 0 0 0 1.7-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.6 1.6 0 0 0-.3 1.7v.1a1.6 1.6 0 0 0 1.5.9H21a2 2 0 0 1 0 4h-.2a1.6 1.6 0 0 0-1.5 1Z" />
    </svg>
  );
}

export default function AdminShell(props: { children: JSX.Element }) {
  const location = useLocation();
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const [checkedSession, setCheckedSession] = createSignal(false);
  const [adminName, setAdminName] = createSignal('Admin');
  const [sidebarOpen, setSidebarOpen] = createSignal(false);
  const [tabsTrackEl, setTabsTrackEl] = createSignal<HTMLDivElement>();
  const [tabRefs, setTabRefs] = createSignal<Record<string, HTMLAnchorElement>>({});
  const [tabIndicator, setTabIndicator] = createSignal({ left: 0, width: 0, ready: false });

  const tabs = createMemo<Tab[]>(() => {
    const path = location.pathname;
    for (const set of TAB_SETS) {
      if (set.prefixes.some((p) => path === p || path.startsWith(`${p}/`))) return set.tabs;
    }
    return [];
  });

  const isTabActive = (tab: Tab) => (tab.exact ? location.pathname === tab.href : location.pathname === tab.href || location.pathname.startsWith(`${tab.href}/`));

  const refreshTabIndicator = () => {
    const activeTab = tabs().find((tab) => isTabActive(tab));
    const track = tabsTrackEl();
    if (!activeTab || !track) {
      setTabIndicator((prev) => ({ ...prev, ready: false }));
      return;
    }
    const el = tabRefs()[activeTab.href];
    if (!el) return;
    setTabIndicator({ left: el.offsetLeft, width: el.offsetWidth, ready: true });
  };

  createEffect(() => {
    tabs();
    location.pathname;
    requestAnimationFrame(refreshTabIndicator);
  });

  onMount(() => {
    const onResize = () => refreshTabIndicator();
    window.addEventListener('resize', onResize);
    onCleanup(() => window.removeEventListener('resize', onResize));

    const isLocalDev =
      typeof window !== 'undefined' && (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1');
    const isPreview =
      searchParams._preview === '1' ||
      (typeof sessionStorage !== 'undefined' && sessionStorage.getItem('nxtgauge_admin_preview') === '1');

    if (isPreview || isLocalDev) {
      if (typeof sessionStorage !== 'undefined') sessionStorage.setItem('nxtgauge_admin_preview', '1');
      setAdminSession();
      setCheckedSession(true);
      return;
    }

    const verify = async () => {
      if (!hasAdminSession()) {
        const from = encodeURIComponent(location.pathname + location.search);
        navigate(`/login?from=${from}`, { replace: true });
        return;
      }
      try {
        const accessToken = typeof sessionStorage !== 'undefined' ? sessionStorage.getItem('nxtgauge_admin_access_token') || '' : '';
        const response = await fetch('/api/gateway/users/auth/me', {
          method: 'GET',
          headers: {
            Accept: 'application/json',
            'x-portal-target': 'admin',
            ...(accessToken ? { Authorization: `Bearer ${accessToken}` } : {}),
          },
          credentials: 'include',
        });
        const payload = await response.json().catch(() => ({}));
        if (!response.ok || isExternalIdentity(payload)) throw new Error('Unauthorized');
        if (payload?.full_name) setAdminName(payload.full_name);
        setCheckedSession(true);
      } catch {
        clearAdminSession();
        const from = encodeURIComponent(location.pathname + location.search);
        navigate(`/login?from=${from}`, { replace: true });
      }
    };

    void verify();
  });

  const onLogout = async () => {
    await fetch('/api/gateway/users/auth/logout', {
      method: 'POST',
      headers: { Accept: 'application/json', 'x-portal-target': 'admin' },
      credentials: 'include',
    }).catch(() => {});
    clearAdminSession();
    if (typeof sessionStorage !== 'undefined') {
      sessionStorage.removeItem('nxtgauge_admin_access_token');
      sessionStorage.removeItem('nxtgauge_admin_preview');
    }
    navigate('/login', { replace: true });
  };

  const adminInitials = createMemo(() => {
    const parts = adminName().split(' ').map((s) => s.trim()).filter(Boolean);
    if (parts.length === 0) return 'AD';
    if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
    return `${parts[0][0] || ''}${parts[1][0] || ''}`.toUpperCase();
  });

  return (
    <div class="min-h-screen bg-[#f0f1f6]">
      <header class="fixed inset-x-0 top-0 z-50 border-b border-[#d8dbe3] bg-[#f6f7fb]">
        <div class="flex h-[86px] items-center justify-between px-8">
          <div class="flex min-w-0 items-center gap-6">
            <button
              type="button"
              class="inline-flex h-10 w-10 items-center justify-center rounded-lg border border-slate-200 text-slate-600 hover:bg-slate-50 lg:hidden"
              onClick={() => setSidebarOpen((v) => !v)}
              aria-label="Toggle sidebar"
            >
              <svg class="h-4 w-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
                <path stroke-linecap="round" d="M4 7h16M4 12h16M4 17h16" />
              </svg>
            </button>
            <A href="/admin" class="flex shrink-0 items-center">
              <img src="/nxtgauge-logo.png" alt="NXTGAUGE" class="h-12 w-auto object-contain" />
            </A>
          </div>

          <div class="flex items-center gap-4">
            <div class="hidden h-[54px] w-[760px] items-center gap-3 rounded-2xl border border-[#daddE8] bg-[#edeef4] px-5 text-[15px] text-[#6a7285] lg:flex">
              <IconSearch />
              <span>Search system operations...</span>
            </div>
            <div class="hidden h-10 w-px bg-[#d9dde7] lg:block" />
            <button type="button" aria-label="Notifications" class="relative inline-flex h-10 w-10 items-center justify-center rounded-full text-[#3e4559] hover:bg-white">
              <span class="absolute right-2 top-2 h-1.5 w-1.5 rounded-full bg-[#fd6216]" />
              <IconBell />
            </button>
            <button type="button" aria-label="Help" class="hidden h-10 w-10 items-center justify-center rounded-full text-[#3e4559] hover:bg-white lg:inline-flex">
              <IconHelp />
            </button>
            <button type="button" aria-label="Settings" class="hidden h-10 w-10 items-center justify-center rounded-full text-[#3e4559] hover:bg-white lg:inline-flex">
              <IconCog />
            </button>
            <div class="hidden h-10 w-px bg-[#d9dde7] lg:block" />
            <div class="hidden items-center gap-3 lg:flex">
              <div class="text-right leading-tight">
                <p class="text-[17px] font-semibold text-[#111827]">{adminName()}</p>
                <p class="text-[14px] text-[#6b7280]">Administrator</p>
              </div>
              <div class="flex h-11 w-11 items-center justify-center overflow-hidden rounded-xl border border-[#d9dce7] bg-gradient-to-br from-[#fef3eb] to-[#ffd9c4] text-[15px] font-bold text-[#fd6216]">
                {adminInitials()}
              </div>
            </div>
          </div>
        </div>
      </header>

      {checkedSession() ? (
        <div class="fixed inset-0 top-[86px] flex">
          <div
            class={`absolute inset-0 z-20 bg-[#0a1d37]/35 transition-opacity lg:hidden ${sidebarOpen() ? 'pointer-events-auto opacity-100' : 'pointer-events-none opacity-0'}`}
            onClick={() => setSidebarOpen(false)}
          />

          <div class={`absolute inset-y-0 left-0 z-30 w-[310px] -translate-x-full transition-transform duration-200 lg:static lg:translate-x-0 ${sidebarOpen() ? 'translate-x-0' : ''}`}>
            <AdminSidebar onNavigate={() => setSidebarOpen(false)} onLogout={onLogout} />
          </div>

          <main class="scrollbar min-w-0 flex-1 overflow-y-auto bg-[#f0f1f6] px-8 pb-8 pt-9">
            <ShowTabs
              tabs={tabs()}
              isTabActive={isTabActive}
              setTabsTrackEl={setTabsTrackEl}
              setTabRefs={setTabRefs}
              tabIndicator={tabIndicator}
            />
            {props.children}
          </main>
        </div>
      ) : (
        <div class="fixed inset-0 top-[86px] flex">
          <div class="hidden w-[310px] border-r border-[#d7d8df] bg-[#f6f6f8] lg:block" />
          <main class="flex flex-1 items-center justify-center bg-[#f0f1f6]">
            <p class="text-sm text-gray-500">Checking session...</p>
          </main>
        </div>
      )}
    </div>
  );
}

function ShowTabs(props: {
  tabs: Tab[];
  isTabActive: (tab: Tab) => boolean;
  setTabsTrackEl: (el: HTMLDivElement) => void;
  setTabRefs: (fn: (prev: Record<string, HTMLAnchorElement>) => Record<string, HTMLAnchorElement>) => void;
  tabIndicator: () => { left: number; width: number; ready: boolean };
}) {
  if (props.tabs.length === 0) return null;

  return (
    <div ref={props.setTabsTrackEl} class="relative mb-7 flex items-center gap-8 border-b border-[#d8dbe3] px-1">
      <For each={props.tabs}>
        {(tab) => (
          <A
            href={tab.href}
            ref={(el) => props.setTabRefs((prev) => ({ ...prev, [tab.href]: el }))}
            aria-current={props.isTabActive(tab) ? 'page' : undefined}
            class={`relative rounded-t-xl px-6 pb-4 pt-4 text-[16px] font-semibold transition-colors ${
              props.isTabActive(tab) ? 'bg-white text-[#111827]' : 'text-[#636b7f] hover:text-[#111827]'
            }`}
          >
            {tab.label}
          </A>
        )}
      </For>
      <div
        class={`absolute bottom-0 h-[3px] bg-[#fd6216] transition-all duration-300 ease-out ${props.tabIndicator().ready ? 'opacity-100' : 'opacity-0'}`}
        style={{ left: `${props.tabIndicator().left}px`, width: `${props.tabIndicator().width}px` }}
      />
    </div>
  );
}
