import { useEffect, useRef, useState, type ReactNode } from 'react';

import type { InstanceContext } from '../app-shell.js';

/** Only these bounded primitives may cross the injected read boundary into the UI. */
export type DeviceNetworkValue = string | number | boolean | null;

export interface WlanStatus {
  readonly enabled?: boolean | null;
  readonly radioState?: string | null;
  readonly connectionState?: string | null;
  readonly activeProfile?: string | null;
  readonly ssid?: string | null;
}

export interface WlanProfile {
  readonly name?: string | null;
  readonly ssid?: string | null;
  readonly security?: string | null;
  readonly enabled?: boolean | null;
  readonly priority?: number | null;
}

export interface NetworkAddress {
  readonly family?: string | null;
  readonly address?: string | null;
  readonly prefixLength?: number | null;
  readonly scope?: string | null;
}

export interface NetworkInterface {
  readonly name?: string | null;
  readonly kind?: string | null;
  readonly state?: string | null;
  readonly macAddress?: string | null;
  readonly mtu?: number | null;
  readonly addresses: readonly NetworkAddress[];
}

export interface DdnsStatus {
  readonly enabled?: boolean | null;
  readonly state?: string | null;
  readonly lastUpdateAt?: string | null;
}

/** Credentials are intentionally absent. Do not add password, token, secret, or username fields. */
export interface DdnsConfig {
  readonly provider?: string | null;
  readonly hostname?: string | null;
  readonly updateIntervalSeconds?: number | null;
}

/** This is aggregate metadata only; raw DDNS log messages are intentionally unsupported. */
export interface DdnsLogSummary {
  readonly totalEntries?: number | null;
  readonly successfulUpdates?: number | null;
  readonly failedUpdates?: number | null;
  readonly lastEventAt?: string | null;
}

export interface DeviceNetworkSnapshot {
  readonly observedAt?: string;
  readonly wlan: {
    readonly status: WlanStatus;
    readonly profiles: readonly WlanProfile[];
  };
  readonly interfaces: readonly NetworkInterface[];
  readonly ddns: {
    readonly status: DdnsStatus;
    readonly config: DdnsConfig;
    readonly logSummary: DdnsLogSummary;
  };
}

export interface DeviceNetworkDataSource {
  /** Implementations are injected by the owner; this module defines no production endpoint. */
  load(instanceId: string, signal: AbortSignal): Promise<DeviceNetworkSnapshot>;
}

export interface DeviceNetworkModuleProps {
  readonly instance: InstanceContext;
  readonly dataSource?: DeviceNetworkDataSource;
  /** Change this owner-provided value to request another read. */
  readonly refreshSignal?: unknown;
}

type ReadState =
  | { kind: 'idle'; ownerId: string }
  | { kind: 'loading'; ownerId: string; snapshot?: DeviceNetworkSnapshot }
  | { kind: 'ready'; ownerId: string; snapshot: DeviceNetworkSnapshot }
  | { kind: 'error'; ownerId: string; snapshot?: DeviceNetworkSnapshot };

const SAFE_LOAD_ERROR = 'Device Network data could not be loaded.';

function display(value: DeviceNetworkValue | undefined): string {
  return value == null ? 'Unavailable' : String(value);
}

function Fields({
  values,
}: {
  values: readonly (readonly [label: string, value: DeviceNetworkValue | undefined])[];
}) {
  return (
    <dl>
      {values.map(([label, value]) => (
        <div key={label}>
          <dt>{label}</dt>
          <dd>{display(value)}</dd>
        </div>
      ))}
    </dl>
  );
}

function Section({ label, children }: { label: string; children: ReactNode }) {
  return (
    <section className="device-network-card" aria-label={label}>
      <h2>{label}</h2>
      {children}
    </section>
  );
}

function SnapshotView({ snapshot }: { snapshot: DeviceNetworkSnapshot }) {
  const status = snapshot.wlan.status;
  const ddnsStatus = snapshot.ddns.status;
  const config = snapshot.ddns.config;
  const logs = snapshot.ddns.logSummary;
  return (
    <>
      {snapshot.observedAt ? <p>Observed {snapshot.observedAt}</p> : null}
      <div className="device-network-grid">
        <Section label="WLAN status">
          <Fields
            values={[
              ['Enabled', status.enabled],
              ['Radio state', status.radioState],
              ['Connection state', status.connectionState],
              ['Active profile', status.activeProfile],
              ['SSID', status.ssid],
            ]}
          />
        </Section>
        <Section label="WLAN profiles">
          {snapshot.wlan.profiles.length ? (
            snapshot.wlan.profiles.map((profile, index) => (
              <article key={`${profile.name ?? 'profile'}-${index}`}>
                <Fields
                  values={[
                    ['Name', profile.name],
                    ['SSID', profile.ssid],
                    ['Security', profile.security],
                    ['Enabled', profile.enabled],
                    ['Priority', profile.priority],
                  ]}
                />
              </article>
            ))
          ) : (
            <p>No WLAN profiles were supplied.</p>
          )}
        </Section>
        <Section label="Interfaces and addresses">
          {snapshot.interfaces.length ? (
            snapshot.interfaces.map((networkInterface, index) => (
              <article key={`${networkInterface.name ?? 'interface'}-${index}`}>
                <Fields
                  values={[
                    ['Name', networkInterface.name],
                    ['Kind', networkInterface.kind],
                    ['State', networkInterface.state],
                    ['MAC address', networkInterface.macAddress],
                    ['MTU', networkInterface.mtu],
                  ]}
                />
                <h3>Addresses</h3>
                {networkInterface.addresses.length ? (
                  <ul>
                    {networkInterface.addresses.map((address, addressIndex) => (
                      <li key={`${address.address ?? 'address'}-${addressIndex}`}>
                        <Fields
                          values={[
                            ['Family', address.family],
                            [
                              'Address',
                              address.address == null
                                ? null
                                : address.prefixLength == null
                                  ? address.address
                                  : `${address.address}/${address.prefixLength}`,
                            ],
                            ['Scope', address.scope],
                          ]}
                        />
                      </li>
                    ))}
                  </ul>
                ) : (
                  <p>No addresses were supplied.</p>
                )}
              </article>
            ))
          ) : (
            <p>No network interfaces were supplied.</p>
          )}
        </Section>
        <Section label="DDNS status">
          <Fields
            values={[
              ['Enabled', ddnsStatus.enabled],
              ['State', ddnsStatus.state],
              ['Last update', ddnsStatus.lastUpdateAt],
            ]}
          />
        </Section>
        <Section label="DDNS configuration">
          <Fields
            values={[
              ['Provider', config.provider],
              ['Hostname', config.hostname],
              ['Update interval (seconds)', config.updateIntervalSeconds],
            ]}
          />
        </Section>
        <Section label="DDNS log summary">
          <Fields
            values={[
              ['Total entries', logs.totalEntries],
              ['Successful updates', logs.successfulUpdates],
              ['Failed updates', logs.failedUpdates],
              ['Last event', logs.lastEventAt],
            ]}
          />
        </Section>
      </div>
      <section className="state-panel" aria-label="Device Network actions">
        <h2>Device Network actions</h2>
        <p>R1 configuration actions are unavailable until executable backend support exists.</p>
        <p>R2 operational actions are unavailable until executable backend support exists.</p>
      </section>
    </>
  );
}

export function DeviceNetworkModule({
  instance,
  dataSource,
  refreshSignal,
}: DeviceNetworkModuleProps) {
  const requestOwner = useRef(0);
  const [retry, setRetry] = useState(0);
  const [state, setState] = useState<ReadState>({ kind: 'idle', ownerId: instance.id });

  useEffect(() => {
    const request = ++requestOwner.current;
    const ownerId = instance.id;
    const controller = new AbortController();

    if (instance.authentication !== 'authenticated' || !dataSource) {
      setState({ kind: 'idle', ownerId });
      return () => controller.abort();
    }

    setState((current) => ({
      kind: 'loading',
      ownerId,
      ...(current.ownerId === ownerId &&
      (current.kind === 'ready' || current.kind === 'error') &&
      current.snapshot
        ? { snapshot: current.snapshot }
        : {}),
    }));
    void dataSource.load(ownerId, controller.signal).then(
      (snapshot) => {
        if (request === requestOwner.current && !controller.signal.aborted)
          setState({ kind: 'ready', ownerId, snapshot });
      },
      (_reason: unknown) => {
        void _reason;
        if (request === requestOwner.current && !controller.signal.aborted)
          setState((current) => ({
            kind: 'error',
            ownerId,
            ...(current.ownerId === ownerId && current.kind === 'loading' && current.snapshot
              ? { snapshot: current.snapshot }
              : {}),
          }));
      },
    );
    return () => controller.abort();
  }, [dataSource, instance.authentication, instance.id, refreshSignal, retry]);

  if (instance.authentication !== 'authenticated') {
    return (
      <div className="state-panel state-error" role="alert">
        Authentication is required before Device Network data can be read for this instance.
      </div>
    );
  }

  if (!dataSource)
    return (
      <div className="state-panel" role="status" aria-label="Device Network unavailable">
        No safe Device Network read data source is available. This console will not invent or call
        an uncontracted production endpoint.
      </div>
    );

  const retainedSnapshot =
    state.ownerId === instance.id && (state.kind === 'loading' || state.kind === 'error')
      ? state.snapshot
      : undefined;

  if ((state.kind === 'idle' || state.kind === 'loading') && !retainedSnapshot)
    return (
      <p role="status" aria-label="Device Network loading status">
        Loading Device Network…
      </p>
    );

  if (state.kind === 'error' && !retainedSnapshot)
    return (
      <div className="state-panel state-error" role="alert">
        <p>Unable to load Device Network: {SAFE_LOAD_ERROR}</p>
        <button type="button" onClick={() => setRetry((value) => value + 1)}>
          Retry loading Device Network
        </button>
      </div>
    );

  const currentSnapshot =
    state.kind === 'ready' && state.ownerId === instance.id ? state.snapshot : retainedSnapshot;
  if (!currentSnapshot) return null;

  return (
    <div className="device-network-module">
      {state.kind === 'loading' ? <p role="status">Refreshing Device Network…</p> : null}
      {state.kind === 'error' ? (
        <div className="state-panel state-error" role="alert">
          <p>Refresh failed; showing the last known Device Network data.</p>
          <button type="button" onClick={() => setRetry((value) => value + 1)}>
            Retry loading Device Network
          </button>
        </div>
      ) : null}
      {instance.freshness !== 'fresh' ? (
        <p className="state-panel" role="status" aria-label="Device Network freshness">
          Device Network data is {instance.freshness}; verify freshness before relying on these
          values.
        </p>
      ) : null}
      <SnapshotView snapshot={currentSnapshot} />
    </div>
  );
}
