import { ConsoleAuthSettings } from './auth/console-auth-settings.js';
import { AuditPage, type AuditDataSource } from './audit/audit-page.js';
import { createAuditApiDataSource } from './audit/audit-api-data-source.js';
import type { ReactNode } from 'react';
import { useEffect, useMemo, useState } from 'react';
import { Tag } from 'animal-island-ui';
import { Icon } from './ui/icon.js';
import {
  AutomationPage,
  type AutomationDataSource as ScheduleDataSource,
} from './automation/automation-page.js';
import { createAutomationApiDataSource } from './automation/automation-api-data-source.js';

import { useControlPlaneEvents } from './events/use-control-plane-events.js';
import { createEventStreamClient, type EventStreamClient } from './events/event-stream-client.js';

import { FleetPage, type FleetDataSource, type FleetSnapshot } from './fleet/fleet-page.js';
import { createFleetApiDataSource } from './fleet/fleet-api-data-source.js';
import {
  createFleetMessagesApiDataSource,
  type FleetMessagesDataSource,
} from './fleet/fleet-messages-api-data-source.js';
import { AutomationModule, type AutomationDataSource } from './instances/automation-module.js';
import { CallsModule, type CallsDataSource } from './instances/calls-module.js';
import { CellularModule, type CellularDataSource } from './instances/cellular-module.js';
import {
  DeviceNetworkModule,
  type DeviceNetworkDataSource,
} from './instances/device-network-module.js';
import { EsimModule, type EsimDataSource } from './instances/esim-module.js';
import { OverviewSystemPage, type OverviewDataSource } from './instances/overview-system.js';
import { InstanceEditor, type InstanceDataSource } from './instances/instance-crud.js';
import { createInstanceApiDataSource } from './instances/instance-api-data-source.js';
import { JobsPage, type JobsDataSource } from './jobs/jobs-page.js';
import { createJobsApiDataSource } from './jobs/jobs-api-data-source.js';
import { MessagesModule, type MessagesDataSource } from './instances/messages-module.js';
import { createMessagesApiDataSource } from './instances/messages-api-data-source.js';
import {
  NotificationsModule,
  type NotificationsDataSource,
} from './instances/notifications-module.js';
import { OtaModule, type OtaDataSource } from './instances/ota-module.js';
import {
  InstanceDetail,
  INSTANCE_MODULE_LABELS,
  type CapabilityDataSource,
  type InstanceCapabilityMap,
} from './instances/instance-detail.js';

export type GlobalSection = 'fleet' | 'automation' | 'settings';
export type InstanceModule =
  | 'overview'
  | 'cellular'
  | 'device-network'
  | 'messages'
  | 'calls'
  | 'esim'
  | 'notifications'
  | 'automation'
  | 'ota';
export type RouteKind =
  | 'redirect'
  | 'fleet'
  | 'automation'
  | 'instance-new'
  | `instance-${InstanceModule}`
  | 'jobs'
  | 'job-detail'
  | 'audit'
  | 'audit-detail'
  | 'settings-instance-detail'
  | 'settings-system'
  | 'not-found';
export interface ResolvedRoute {
  kind: RouteKind;
  pathname: string;
  params?: Readonly<Record<string, string>>;
  to?: string;
}
export interface InstanceContext {
  id: string;
  name: string;
  origin: string;
  status: 'online' | 'offline' | 'auth-required' | 'degraded' | 'unknown';
  authentication: 'authenticated' | 'auth-required' | 'unknown';
  freshness: 'fresh' | 'stale' | 'expired' | 'unknown';
  /** Control-plane config revision for prepare/execute CAS when known. */
  revision?: number;
  resources?: Readonly<{
    cpuPercent?: number;
    memoryPercent?: number;
    maxTemperatureCelsius?: number;
    phoneNumbers?: readonly string[];
  }>;
  resourceSummaryState?: 'loading' | 'ready' | 'unavailable';
}
export interface AppShellProps {
  pathname: string;
  version?: string;
  instance?: InstanceContext;
  fleetDataSource?: FleetDataSource;
  fleetMessagesDataSource?: FleetMessagesDataSource;
  fleetData?: FleetSnapshot;
  instanceDataSource?: InstanceDataSource;
  capabilities?: InstanceCapabilityMap;
  capabilityDataSource?: CapabilityDataSource;
  overviewDataSource?: OverviewDataSource;
  cellularDataSource?: CellularDataSource;
  deviceNetworkDataSource?: DeviceNetworkDataSource;
  messagesDataSource?: MessagesDataSource;
  callsDataSource?: CallsDataSource;
  esimDataSource?: EsimDataSource;
  notificationsDataSource?: NotificationsDataSource;
  automationDataSource?: AutomationDataSource;
  otaDataSource?: OtaDataSource;
  jobsDataSource?: JobsDataSource;
  auditDataSource?: AuditDataSource;
  scheduleDataSource?: ScheduleDataSource;
  eventStreamClient?: EventStreamClient;
}

const MODULE_LABELS = INSTANCE_MODULE_LABELS;
const INSTANCE_MODULES = new Set(Object.keys(MODULE_LABELS));

function normalize(pathname: string): string {
  const path = pathname.split(/[?#]/u, 1)[0] ?? '/';
  return path === '/' ? path : path.replace(/\/+$/u, '') || '/';
}
function decode(value: string): string {
  try {
    return decodeURIComponent(value);
  } catch {
    return value;
  }
}

export function resolveRoute(input: string): ResolvedRoute {
  const pathname = normalize(input);
  if (pathname === '/') return { kind: 'redirect', pathname, to: '/fleet' };
  if (pathname === '/settings/instances')
    return { kind: 'redirect', pathname, to: '/settings/system' };
  const staticRoutes: Readonly<Record<string, RouteKind>> = {
    '/fleet': 'fleet',
    '/automation': 'automation',
    '/instances/new': 'instance-new',
    '/jobs': 'jobs',
    '/audit': 'audit',
    '/settings/system': 'settings-system',
  };
  if (staticRoutes[pathname]) return { kind: staticRoutes[pathname], pathname };
  const parts = pathname.split('/').filter(Boolean);
  if (parts[0] === 'instances' && parts.length === 3 && INSTANCE_MODULES.has(parts[2] ?? ''))
    return {
      kind: `instance-${parts[2] as InstanceModule}`,
      pathname,
      params: { instanceId: decode(parts[1] ?? '') },
    };
  if (parts[0] === 'jobs' && parts.length === 2)
    return { kind: 'job-detail', pathname, params: { jobId: decode(parts[1] ?? '') } };
  if (parts[0] === 'audit' && parts.length === 2)
    return { kind: 'audit-detail', pathname, params: { eventId: decode(parts[1] ?? '') } };
  if (parts[0] === 'settings' && parts[1] === 'instances' && parts.length === 3)
    return {
      kind: 'settings-instance-detail',
      pathname,
      params: { instanceId: decode(parts[2] ?? '') },
    };
  return { kind: 'not-found', pathname };
}

function section(route: ResolvedRoute): GlobalSection | undefined {
  if (route.kind === 'fleet' || route.kind === 'instance-new' || route.kind.startsWith('instance-'))
    return 'fleet';
  if (route.kind === 'automation' || route.kind.startsWith('job') || route.kind.startsWith('audit'))
    return 'automation';
  if (route.kind.startsWith('settings')) return 'settings';
  return undefined;
}

function Page({
  route,
  fleetDataSource,
  fleetMessagesDataSource,
  fleetData,
  instance,
  instanceDataSource,
  capabilities,
  capabilityDataSource,
  overviewDataSource,
  cellularDataSource,
  deviceNetworkDataSource,
  messagesDataSource,
  callsDataSource,
  esimDataSource,
  notificationsDataSource,
  automationDataSource,
  otaDataSource,
  jobsDataSource,
  auditDataSource,
  scheduleDataSource,
  fleetRefreshSignal,
  detailRefreshSignal,
}: {
  route: ResolvedRoute;
  fleetDataSource: FleetDataSource | undefined;
  fleetMessagesDataSource: FleetMessagesDataSource | undefined;
  fleetData: FleetSnapshot | undefined;
  instance: InstanceContext | undefined;
  instanceDataSource: InstanceDataSource | undefined;
  capabilities: InstanceCapabilityMap | undefined;
  capabilityDataSource: CapabilityDataSource | undefined;
  overviewDataSource: OverviewDataSource | undefined;
  cellularDataSource: CellularDataSource | undefined;
  deviceNetworkDataSource: DeviceNetworkDataSource | undefined;
  messagesDataSource: MessagesDataSource | undefined;
  callsDataSource: CallsDataSource | undefined;
  esimDataSource: EsimDataSource | undefined;
  notificationsDataSource: NotificationsDataSource | undefined;
  automationDataSource: AutomationDataSource | undefined;
  otaDataSource: OtaDataSource | undefined;
  jobsDataSource: JobsDataSource | undefined;
  auditDataSource: AuditDataSource | undefined;
  scheduleDataSource: ScheduleDataSource;
  fleetRefreshSignal: number;
  detailRefreshSignal: number;
}): ReactNode {
  if (route.kind === 'fleet')
    return (
      <FleetPage
        {...(fleetDataSource ? { dataSource: fleetDataSource } : {})}
        {...(fleetMessagesDataSource ? { messagesDataSource: fleetMessagesDataSource } : {})}
        {...(fleetData ? { initialData: fleetData } : {})}
        refreshSignal={fleetRefreshSignal}
      />
    );
  if (route.kind === 'instance-new')
    return (
      <InstanceEditor
        mode="create"
        {...(instanceDataSource ? { dataSource: instanceDataSource } : {})}
      />
    );
  if (route.kind === 'settings-instance-detail')
    return (
      <InstanceEditor
        mode="edit"
        {...(route.params?.instanceId ? { instanceId: route.params.instanceId } : {})}
        {...(instanceDataSource ? { dataSource: instanceDataSource } : {})}
      />
    );
  if (route.kind === 'automation' || route.kind === 'jobs' || route.kind === 'audit')
    return (
      <AutomationPage
        dataSource={scheduleDataSource}
        initialTab={
          route.kind === 'jobs' ? 'runs' : route.kind === 'audit' ? 'records' : 'schedules'
        }
        runsContent={
          <JobsPage
            {...(jobsDataSource ? { dataSource: jobsDataSource } : {})}
            refreshSignal={fleetRefreshSignal}
          />
        }
        recordsContent={
          <AuditPage
            {...(auditDataSource ? { dataSource: auditDataSource } : {})}
            refreshSignal={fleetRefreshSignal}
          />
        }
      />
    );
  if (route.kind === 'settings-system') return <ConsoleAuthSettings />;
  if (route.kind === 'not-found')
    return (
      <section>
        <h1>页面未找到</h1>
        <p>请求的控制台页面不存在。</p>
        <a href="/fleet">返回实例总览</a>
      </section>
    );
  if (route.kind.startsWith('instance-')) {
    const module = route.kind.slice('instance-'.length) as InstanceModule;
    return (
      <InstanceDetail
        instanceId={route.params?.instanceId ?? ''}
        module={module}
        {...(instance ? { instance } : {})}
        {...(capabilities ? { capabilities } : {})}
        {...(capabilityDataSource ? { capabilityDataSource } : {})}
        {...(module === 'overview' && instance
          ? {
              moduleContent: (
                <OverviewSystemPage
                  instance={instance}
                  {...(overviewDataSource ? { dataSource: overviewDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                  {...(instance.revision !== undefined ? { revision: instance.revision } : {})}
                />
              ),
            }
          : {})}
        {...(module === 'cellular' && instance
          ? {
              moduleContent: (
                <CellularModule
                  instance={instance}
                  {...(cellularDataSource ? { dataSource: cellularDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
        {...(module === 'device-network' && instance
          ? {
              moduleContent: (
                <DeviceNetworkModule
                  instance={instance}
                  {...(deviceNetworkDataSource ? { dataSource: deviceNetworkDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
        {...(module === 'messages' && instance
          ? {
              moduleContent: (
                <MessagesModule
                  instance={instance}
                  {...(messagesDataSource ? { dataSource: messagesDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
        {...(module === 'calls' && instance
          ? {
              moduleContent: (
                <CallsModule
                  instance={instance}
                  {...(callsDataSource ? { dataSource: callsDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
        {...(module === 'esim' && instance
          ? {
              moduleContent: (
                <EsimModule
                  instance={instance}
                  {...(esimDataSource ? { dataSource: esimDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
        {...(module === 'notifications' && instance
          ? {
              moduleContent: (
                <NotificationsModule
                  instance={instance}
                  {...(notificationsDataSource ? { dataSource: notificationsDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
        {...(module === 'automation' && instance
          ? {
              moduleContent: (
                <AutomationModule
                  instance={instance}
                  {...(automationDataSource ? { dataSource: automationDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
        {...(module === 'ota' && instance
          ? {
              moduleContent: (
                <OtaModule
                  instance={instance}
                  {...(otaDataSource ? { dataSource: otaDataSource } : {})}
                  refreshSignal={detailRefreshSignal}
                />
              ),
            }
          : {})}
      />
    );
  }
  const labels: Partial<Record<RouteKind, string>> = {
    'instance-new': '添加实例',
    jobs: '任务',
    'job-detail': '任务详情',
    audit: '审计',
    'audit-detail': '审计事件',
    'settings-instance-detail': '实例设置',
    'settings-system': '系统设置',
  };
  return (
    <section>
      <h1>{labels[route.kind] ?? '多实例 SimAdmin 管理台'}</h1>
      <p>此页面已准备好展示结构化数据与操作。</p>
    </section>
  );
}

function displayConsoleVersion(version: string | undefined): string | undefined {
  if (!version) return undefined;
  const trimmed = version.trim();
  if (!trimmed || trimmed.toLowerCase() === 'dev' || trimmed === '0.0.0') return undefined;
  return trimmed;
}

const GLOBAL_NAVIGATION: readonly {
  section: GlobalSection;
  href: string;
  label: string;
  icon: 'grid' | 'jobs' | 'settings';
}[] = [
  { section: 'fleet', href: '/fleet', label: '节点', icon: 'grid' },
  { section: 'automation', href: '/automation', label: '自动化', icon: 'jobs' },
  { section: 'settings', href: '/settings/system', label: '设置', icon: 'settings' },
];

const STREAM_LABELS = {
  connecting: '正在连接',
  open: '实时连接正常',
  reconnecting: '正在重新连接',
  resetting: '正在同步状态',
  closed: '实时连接已关闭',
} as const;

const STREAM_COLORS = {
  connecting: 'app-yellow',
  open: 'app-teal',
  reconnecting: 'app-orange',
  resetting: 'app-yellow',
  closed: 'app-red',
} as const;

export function AppShell({
  pathname,
  version = 'dev',
  instance,
  fleetDataSource,
  fleetMessagesDataSource,
  fleetData,
  instanceDataSource,
  capabilities,
  capabilityDataSource,
  overviewDataSource,
  cellularDataSource,
  deviceNetworkDataSource,
  messagesDataSource,
  callsDataSource,
  esimDataSource,
  notificationsDataSource,
  automationDataSource,
  otaDataSource,
  jobsDataSource,
  auditDataSource,
  scheduleDataSource,
  eventStreamClient,
}: AppShellProps) {
  const defaultEventStreamClient = useMemo(() => createEventStreamClient(), []);
  const defaultFleetDataSource = useMemo(() => createFleetApiDataSource(), []);
  const defaultFleetMessagesDataSource = useMemo(() => createFleetMessagesApiDataSource(), []);
  const defaultInstanceDataSource = useMemo(() => createInstanceApiDataSource(), []);
  const defaultMessagesDataSource = useMemo(() => createMessagesApiDataSource(), []);
  const resolvedJobsDataSource = useMemo(
    () => jobsDataSource ?? createJobsApiDataSource(),
    [jobsDataSource],
  );
  const resolvedAuditDataSource = useMemo(
    () => auditDataSource ?? createAuditApiDataSource(),
    [auditDataSource],
  );
  const resolvedScheduleDataSource = useMemo(
    () => scheduleDataSource ?? createAutomationApiDataSource(),
    [scheduleDataSource],
  );
  const resolved = resolveRoute(pathname);
  const route = resolved.kind === 'redirect' ? resolveRoute(resolved.to ?? '/fleet') : resolved;
  const routeInstanceId = route.params?.instanceId;
  const resolvedInstanceDataSource = instanceDataSource ?? defaultInstanceDataSource;
  const [loadedInstance, setLoadedInstance] = useState<InstanceContext>();
  const [instanceLoading, setInstanceLoading] = useState(false);
  const [instanceLoadFailed, setInstanceLoadFailed] = useState(false);

  useEffect(() => {
    setLoadedInstance(undefined);
    setInstanceLoadFailed(false);
    if (!routeInstanceId || instance?.id === routeInstanceId) {
      setInstanceLoading(false);
      return;
    }
    const controller = new AbortController();
    let active = true;
    setInstanceLoading(true);
    const fleetLoad = (fleetDataSource ?? defaultFleetDataSource)
      .load(controller.signal, (partial) => {
        if (!active) return;
        const fleetOwner = partial.instances.find((candidate) => candidate.id === routeInstanceId);
        const status = partial.statuses.get(routeInstanceId);
        if (!fleetOwner && !status) return;
        setLoadedInstance((current) => {
          if (!current || current.id !== routeInstanceId) return current;
          const routeStatus = !status
            ? current.status
            : !status.reachable
              ? 'offline'
              : status.authenticated === false
                ? 'auth-required'
                : 'online';
          const freshness = status?.summary?.freshness;
          const nextRevision = fleetOwner?.revision ?? current.revision;
          return {
            ...current,
            origin: fleetOwner?.url ?? current.origin,
            status: routeStatus,
            authentication:
              status?.authenticated === true
                ? 'authenticated'
                : status?.authenticated === false
                  ? 'auth-required'
                  : current.authentication,
            freshness:
              freshness === 'fresh' || freshness === 'stale' || freshness === 'expired'
                ? freshness
                : current.freshness,
            ...(nextRevision === undefined ? {} : { revision: nextRevision }),
            ...(status?.summary?.resources ? { resources: status.summary.resources } : {}),
            resourceSummaryState: status?.summary?.resources
              ? 'ready'
              : current.resourceSummaryState === 'ready'
                ? 'ready'
                : 'loading',
          };
        });
      })
      .then(
        (fleet) => ({ ok: true as const, fleet }),
        () => ({ ok: false as const }),
      );
    void resolvedInstanceDataSource.get(routeInstanceId).then(
      (owner) => {
        if (!active) return;
        if (owner.id !== routeInstanceId) {
          setInstanceLoadFailed(true);
          setInstanceLoading(false);
          return;
        }
        setLoadedInstance({
          id: owner.id,
          name: owner.name,
          origin: owner.origin,
          status: 'unknown',
          authentication: 'unknown',
          freshness: 'unknown',
          ...(owner.revision === undefined ? {} : { revision: owner.revision }),
          resourceSummaryState: 'loading',
        });
        setInstanceLoading(false);

        void fleetLoad.then((result) => {
          if (!active) return;
          if (!result.ok) {
            setLoadedInstance((current) =>
              current?.id === routeInstanceId
                ? { ...current, resourceSummaryState: 'unavailable' }
                : current,
            );
            return;
          }
          const fleet = result.fleet;
          const fleetOwner = fleet.instances.find((candidate) => candidate.id === routeInstanceId);
          const status = fleet.statuses.get(routeInstanceId);
          const routeStatus = !status
            ? 'unknown'
            : !status.reachable
              ? 'offline'
              : status.authenticated === false
                ? 'auth-required'
                : 'online';
          const freshness = status?.summary?.freshness;
          const nextRevision = fleetOwner?.revision ?? owner.revision;
          setLoadedInstance({
            id: owner.id,
            name: owner.name,
            origin: fleetOwner?.url ?? owner.origin,
            status: routeStatus,
            authentication:
              status?.authenticated === true
                ? 'authenticated'
                : status?.authenticated === false
                  ? 'auth-required'
                  : 'unknown',
            freshness:
              freshness === 'fresh' || freshness === 'stale' || freshness === 'expired'
                ? freshness
                : 'unknown',
            ...(nextRevision === undefined ? {} : { revision: nextRevision }),
            ...(status?.summary?.resources ? { resources: status.summary.resources } : {}),
            resourceSummaryState: status ? 'ready' : 'unavailable',
          });
        });
      },
      () => {
        if (!active) return;
        setInstanceLoadFailed(true);
        setInstanceLoading(false);
      },
    );
    return () => {
      active = false;
      controller.abort();
    };
  }, [
    defaultFleetDataSource,
    fleetDataSource,
    instance,
    resolvedInstanceDataSource,
    routeInstanceId,
  ]);

  const routeInstance = instance?.id === routeInstanceId ? instance : loadedInstance;
  const refresh = useControlPlaneEvents(
    routeInstanceId,
    eventStreamClient ?? defaultEventStreamClient,
  );
  const currentSection = section(route);
  const consoleVersion = displayConsoleVersion(version);
  return (
    <div className="app-shell" data-route={route.kind} data-section={currentSection ?? 'other'}>
      <a className="skip-link" href="#main-content">
        跳到主要内容
      </a>
      <header className="app-topbar">
        <a className="product-name" href="/fleet" aria-label="多实例 SimAdmin 管理台首页">
          <span className="product-mark" aria-hidden="true">
            <span className="product-signal">
              <i />
              <i />
              <i />
            </span>
          </span>
          <span className="product-copy">
            <strong>SimAdmin Control</strong>
          </span>
        </a>
        <nav className="global-navigation" aria-label="全局导航">
          {GLOBAL_NAVIGATION.map((item) => (
            <a
              key={item.section}
              href={item.href}
              aria-current={currentSection === item.section ? 'page' : undefined}
            >
              <Icon name={item.icon} />
              <span>{item.label}</span>
            </a>
          ))}
        </nav>
        <div className="topbar-actions">
          <Tag
            className="connection-status"
            color={STREAM_COLORS[refresh.stream]}
            variant="soft"
            size="small"
          >
            <span data-state={refresh.stream} role="status" aria-label="实时连接状态">
              {STREAM_LABELS[refresh.stream]}
            </span>
          </Tag>
          {consoleVersion ? (
            <Tag className="version-badge" color="brown" variant="soft" size="small">
              <span aria-label={`控制台版本 ${consoleVersion}`}>v{consoleVersion}</span>
            </Tag>
          ) : null}
        </div>
      </header>
      <div className="app-layout app-layout-single">
        <main id="main-content" tabIndex={-1}>
          {routeInstanceId && instanceLoading ? (
            <p role="status" aria-label="实例加载状态">
              正在加载实例…
            </p>
          ) : routeInstanceId && instanceLoadFailed ? (
            <p role="alert" className="state-panel state-error">
              无法加载此实例，请返回总览后重试。
            </p>
          ) : (
            <Page
              route={route}
              fleetDataSource={fleetDataSource ?? defaultFleetDataSource}
              fleetMessagesDataSource={fleetMessagesDataSource ?? defaultFleetMessagesDataSource}
              fleetData={fleetData}
              instance={routeInstance}
              instanceDataSource={resolvedInstanceDataSource}
              capabilities={capabilities}
              capabilityDataSource={capabilityDataSource}
              overviewDataSource={overviewDataSource}
              cellularDataSource={cellularDataSource}
              deviceNetworkDataSource={deviceNetworkDataSource}
              messagesDataSource={messagesDataSource ?? defaultMessagesDataSource}
              callsDataSource={callsDataSource}
              esimDataSource={esimDataSource}
              notificationsDataSource={notificationsDataSource}
              automationDataSource={automationDataSource}
              otaDataSource={otaDataSource}
              jobsDataSource={resolvedJobsDataSource}
              auditDataSource={resolvedAuditDataSource}
              scheduleDataSource={resolvedScheduleDataSource}
              fleetRefreshSignal={refresh.fleet}
              detailRefreshSignal={refresh.detail}
            />
          )}
        </main>
      </div>
      <footer className="app-footer" aria-label="项目与组件库信息">
        <p>
          UI: <a href="https://github.com/guokaigdg/animal-island-ui">animal-island-ui</a>
          <span aria-hidden="true"> · </span>
          <a href="https://creativecommons.org/licenses/by-nc/4.0/">CC BY-NC 4.0</a>
        </p>
      </footer>
    </div>
  );
}
