// SPEC: HWLAB-ESO-UI-20260630 ESO UI draft-2026-06-30-p1-readonly-ui.
// Responsibility: normalize admin secrets read model for the Cloud Web view.
import type { AdminSecretsEvent, AdminSecretsExternalSecret, AdminSecretsStore, AdminSecretsSummaryResponse, AdminSecretsTarget } from "@/types";
import { asRecord, firstNonEmptyString, formatRelativeTime, nonEmptyString } from "@/utils";

export interface AdminSecretsTargetView {
  node: string;
  lane: string;
  runtimeNamespace: string;
  infraNamespace: string;
  publicUrl: string;
  source: string;
  sourceRef: string;
  upstreamSourceRef: string;
}

export interface AdminSecretsSummaryView {
  contractVersion: string;
  status: string;
  generatedAt: string;
  valuesPrinted: boolean;
  secretMaterialStored: boolean;
  permissions: { plan: boolean; apply: boolean; valuesPrinted: boolean };
  target: AdminSecretsTargetView;
  sourcePath: string;
  sourcePresent: boolean;
  counts: { externalSecrets: number; ready: number; pending: number; errors: number; events: number };
  eso: { controller: string; webhook: string; certController: string };
  stores: AdminSecretsStoreView[];
  consumerRollout: { total: number; ready: number; pending: number; revision: string };
  evidence: { source: string; issue: string; command: string; validatedAt: string; fingerprint: string; valuesPrinted: boolean };
}

export interface AdminSecretsStoreView {
  kind: string;
  name: string;
  namespace: string;
  scope: string;
  status: string;
  reason: string;
}

export interface AdminSecretsRow {
  id: string;
  name: string;
  namespace: string;
  cluster: string;
  status: string;
  ready: boolean;
  reason: string;
  refreshInterval: string;
  createdAt: string;
  lastUpdated: string;
  ageText: string;
  lastRefreshTime: string;
  targetNode: string;
  targetLane: string;
  targetSecretName: string;
  targetSecretNamespace: string;
  targetSecretResourceVersion: string;
  storeKind: string;
  storeName: string;
  storeScope: string;
  storeText: string;
  keySummary: string;
  fingerprint: string;
  consumerSummary: string;
  valuesPrinted: boolean;
  secretMaterialStored: boolean;
  raw: AdminSecretsExternalSecret;
}

export interface AdminSecretsDetailView extends AdminSecretsRow {
  metadata: Array<{ label: string; value: string }>;
  data: Array<{ targetKey: string; remotePath: string; property: string; version: string; fingerprint: string }>;
  targetKeys: Array<{ key: string; presence: string; fingerprint: string }>;
  conditions: Array<{ type: string; status: string; reason: string; lastTransitionTime: string }>;
  consumers: Array<{ serviceId: string; kind: string; injectAs: string; envName: string; status: string; rollout: string; revision: string }>;
  provenance: Array<{ label: string; value: string }>;
}

export interface AdminSecretsEventView {
  id: string;
  status: string;
  reason: string;
  namespace: string;
  resource: string;
  message: string;
  observedAt: string;
  source: string;
  traceId: string;
  jobId: string;
  valuesPrinted: boolean;
}

export function normalizeAdminSecretsSummary(payload: AdminSecretsSummaryResponse | null | undefined): AdminSecretsSummaryView {
  const summary = asRecord(payload?.summary);
  const counts = asRecord(summary?.counts);
  const eso = asRecord(summary?.eso);
  const consumerRollout = asRecord(summary?.consumerRollout);
  const evidence = asRecord(summary?.latestEvidence);
  const source = asRecord(payload?.source);
  const permissions = asRecord(payload?.permissions);
  return {
    contractVersion: nonEmptyString(payload?.contractVersion) ?? "hwlab-admin-secrets-v1",
    status: nonEmptyString(summary?.status) ?? nonEmptyString(payload?.status) ?? "Unknown",
    generatedAt: nonEmptyString(payload?.generatedAt) ?? "",
    valuesPrinted: payload?.valuesPrinted === false ? false : true,
    secretMaterialStored: payload?.secretMaterialStored === false ? false : true,
    permissions: {
      plan: permissions?.plan === true || permissions?.["admin.secrets.plan"] === true,
      apply: permissions?.apply === true,
      valuesPrinted: permissions?.valuesPrinted === true
    },
    target: normalizeTarget(payload?.target),
    sourcePath: nonEmptyString(source?.path) ?? "-",
    sourcePresent: source?.present === true,
    counts: {
      externalSecrets: numberValue(counts?.externalSecrets),
      ready: numberValue(counts?.ready),
      pending: numberValue(counts?.pending),
      errors: numberValue(counts?.errors),
      events: numberValue(counts?.events)
    },
    eso: {
      controller: nonEmptyString(eso?.controller) ?? "Unknown",
      webhook: nonEmptyString(eso?.webhook) ?? "Unknown",
      certController: nonEmptyString(eso?.certController) ?? "Unknown"
    },
    stores: Array.isArray(summary?.stores) ? summary.stores.map((item) => normalizeStore(item)).filter(Boolean) : [],
    consumerRollout: {
      total: numberValue(consumerRollout?.total),
      ready: numberValue(consumerRollout?.ready),
      pending: numberValue(consumerRollout?.pending),
      revision: nonEmptyString(consumerRollout?.revision) ?? "-"
    },
    evidence: {
      source: nonEmptyString(evidence?.source) ?? "-",
      issue: nonEmptyString(evidence?.issue) ?? "-",
      command: nonEmptyString(evidence?.command) ?? "-",
      validatedAt: nonEmptyString(evidence?.validatedAt) ?? "",
      fingerprint: nonEmptyString(evidence?.fingerprint) ?? "-",
      valuesPrinted: evidence?.valuesPrinted === false ? false : true
    }
  };
}

export function normalizeAdminSecretsRows(items: AdminSecretsExternalSecret[] | null | undefined): AdminSecretsRow[] {
  return Array.isArray(items) ? items.map((item) => normalizeRow(item)).sort((left, right) => `${left.namespace}/${left.name}`.localeCompare(`${right.namespace}/${right.name}`)) : [];
}

export function normalizeAdminSecretsDetail(item: AdminSecretsExternalSecret | null | undefined): AdminSecretsDetailView | null {
  if (!item) return null;
  const row = normalizeRow(item);
  const targetSecret = asRecord(item.targetSecret);
  const provenance = asRecord(item.provenance);
  return {
    ...row,
    metadata: [
      fact("name", row.name),
      fact("namespace", row.namespace),
      fact("cluster", row.cluster),
      fact("refreshInterval", row.refreshInterval),
      fact("createdAt", row.createdAt),
      fact("lastUpdated", row.lastUpdated),
      fact("reason", row.reason),
      fact("targetSecretNamespace", row.targetSecretNamespace),
      fact("resourceVersion", row.targetSecretResourceVersion),
      fact("valuesPrinted", String(row.valuesPrinted)),
      fact("secretMaterialStored", String(row.secretMaterialStored))
    ].filter((item): item is { label: string; value: string } => Boolean(item)),
    data: Array.isArray(item.data) ? item.data.map((entry) => {
      const remoteRef = asRecord(entry.remoteRef);
      return {
        targetKey: nonEmptyString(entry.targetKey) ?? "-",
        remotePath: nonEmptyString(remoteRef?.path) ?? "-",
        property: nonEmptyString(remoteRef?.property) ?? "-",
        version: nonEmptyString(remoteRef?.version) ?? "-",
        fingerprint: nonEmptyString(remoteRef?.fingerprint) ?? "-"
      };
    }) : [],
    targetKeys: Array.isArray(targetSecret?.keys) ? targetSecret.keys.map((entry) => ({
      key: nonEmptyString(entry.key) ?? "-",
      presence: nonEmptyString(entry.presence) ?? "unknown",
      fingerprint: nonEmptyString(entry.fingerprint) ?? "-"
    })) : [],
    conditions: Array.isArray(item.conditions) ? item.conditions.map((entry) => ({
      type: nonEmptyString(entry.type) ?? "Ready",
      status: nonEmptyString(entry.status) ?? row.status,
      reason: nonEmptyString(entry.reason) ?? row.reason,
      lastTransitionTime: nonEmptyString(entry.lastTransitionTime) ?? row.lastUpdated
    })) : [{ type: "Ready", status: row.status, reason: row.reason, lastTransitionTime: row.lastUpdated }],
    consumers: Array.isArray(item.consumers) ? item.consumers.map((entry) => ({
      serviceId: nonEmptyString(entry.serviceId) ?? "-",
      kind: nonEmptyString(entry.kind) ?? "-",
      injectAs: nonEmptyString(entry.injectAs) ?? "-",
      envName: nonEmptyString(entry.envName) ?? "-",
      status: nonEmptyString(entry.status) ?? "Unknown",
      rollout: nonEmptyString(entry.rollout) ?? "Unknown",
      revision: nonEmptyString(entry.revision) ?? "-"
    })) : [],
    provenance: [
      fact("configSource", provenance?.configSource),
      fact("statusSource", provenance?.statusSource),
      fact("issue", provenance?.issue),
      fact("command", provenance?.command),
      fact("validatedAt", provenance?.validatedAt)
    ].filter((item): item is { label: string; value: string } => Boolean(item))
  };
}

export function normalizeAdminSecretsEvents(items: AdminSecretsEvent[] | null | undefined): AdminSecretsEventView[] {
  if (!Array.isArray(items)) return [];
  return items.map((item, index) => {
    const resourceKind = nonEmptyString(item.resourceKind) ?? "SecretPlane";
    const resourceName = nonEmptyString(item.resourceName) ?? "-";
    return {
      id: `${nonEmptyString(item.observedAt) ?? "event"}:${resourceKind}:${resourceName}:${index}`,
      status: nonEmptyString(item.status) ?? "Unknown",
      reason: nonEmptyString(item.reason) ?? "-",
      namespace: nonEmptyString(item.namespace) ?? "-",
      resource: `${resourceKind}/${resourceName}`,
      message: nonEmptyString(item.message) ?? "-",
      observedAt: nonEmptyString(item.observedAt) ?? "",
      source: nonEmptyString(item.source) ?? "-",
      traceId: nonEmptyString(item.traceId) ?? "-",
      jobId: nonEmptyString(item.jobId) ?? "-",
      valuesPrinted: item.valuesPrinted === false ? false : true
    };
  });
}

function normalizeRow(item: AdminSecretsExternalSecret): AdminSecretsRow {
  const target = normalizeTarget(item.target);
  const store = normalizeStore(item.store);
  const targetSecret = asRecord(item.targetSecret);
  const keys = Array.isArray(targetSecret?.keys) ? targetSecret.keys : [];
  const consumers = Array.isArray(item.consumers) ? item.consumers : [];
  const cluster = firstNonEmptyString(item.cluster, `${target.node}/${target.lane}`) ?? "-";
  const createdAt = nonEmptyString(item.createdAt) ?? "";
  const lastUpdated = firstNonEmptyString(item.lastUpdated, item.lastRefreshTime, item.ageSource, item.createdAt) ?? "";
  const ageSource = firstNonEmptyString(item.ageSource, item.createdAt, lastUpdated) ?? "";
  return {
    id: nonEmptyString(item.id) ?? `${nonEmptyString(item.namespace) ?? "-"}:${nonEmptyString(item.name) ?? "-"}`,
    name: nonEmptyString(item.name) ?? "-",
    namespace: nonEmptyString(item.namespace) ?? target.runtimeNamespace,
    cluster,
    status: nonEmptyString(item.status) ?? "Unknown",
    ready: item.ready === true,
    reason: nonEmptyString(item.reason) ?? "-",
    refreshInterval: nonEmptyString(item.refreshInterval) ?? "-",
    createdAt,
    lastUpdated,
    ageText: ageSource ? formatRelativeTime(ageSource) : "-",
    lastRefreshTime: nonEmptyString(item.lastRefreshTime) ?? lastUpdated,
    targetNode: target.node,
    targetLane: target.lane,
    targetSecretName: nonEmptyString(targetSecret?.name) ?? "-",
    targetSecretNamespace: nonEmptyString(targetSecret?.namespace) ?? nonEmptyString(item.namespace) ?? target.runtimeNamespace,
    targetSecretResourceVersion: nonEmptyString(targetSecret?.resourceVersion) ?? "-",
    storeKind: store.kind,
    storeName: store.name,
    storeScope: store.scope,
    storeText: `${store.kind}/${store.name}`,
    keySummary: keys.map((entry) => `${nonEmptyString(entry.key) ?? "-"}:${nonEmptyString(entry.presence) ?? "unknown"}`).join(", ") || "-",
    fingerprint: nonEmptyString(targetSecret?.fingerprint) ?? "-",
    consumerSummary: consumers.map((entry) => `${nonEmptyString(entry.serviceId) ?? "-"}:${nonEmptyString(entry.rollout) ?? "Unknown"}`).join(", ") || "-",
    valuesPrinted: item.valuesPrinted === false ? false : true,
    secretMaterialStored: item.secretMaterialStored === false ? false : true,
    raw: item
  };
}

function normalizeTarget(value: AdminSecretsTarget | undefined): AdminSecretsTargetView {
  return {
    node: nonEmptyString(value?.node) ?? "-",
    lane: nonEmptyString(value?.lane) ?? "-",
    runtimeNamespace: nonEmptyString(value?.runtimeNamespace) ?? "-",
    infraNamespace: nonEmptyString(value?.infraNamespace) ?? "-",
    publicUrl: nonEmptyString(value?.publicUrl) ?? "-",
    source: nonEmptyString(value?.source) ?? "-",
    sourceRef: nonEmptyString(value?.sourceRef) ?? "-",
    upstreamSourceRef: nonEmptyString(value?.upstreamSourceRef) ?? "-"
  };
}

function normalizeStore(value: AdminSecretsStore | unknown): AdminSecretsStoreView {
  const item = asRecord(value);
  return {
    kind: nonEmptyString(item?.kind) ?? "-",
    name: nonEmptyString(item?.name) ?? "-",
    namespace: nonEmptyString(item?.namespace) ?? "-",
    scope: nonEmptyString(item?.scope) ?? "-",
    status: nonEmptyString(item?.status) ?? "Unknown",
    reason: nonEmptyString(item?.reason) ?? "-"
  };
}

function fact(label: string, value: unknown): { label: string; value: string } | null {
  const text = nonEmptyString(value);
  return text ? { label, value: text } : null;
}

function numberValue(value: unknown): number {
  const number = Number(value ?? 0);
  return Number.isFinite(number) ? number : 0;
}
