/**
 * Deterministic fixture dataset for the mocked query service.
 * Object types use the report-stream vocabulary (manifest / certificate / aspa).
 */

export const RUN_2 = {
  schemaVersion: 1,
  runId: "run_0002",
  runSeq: 2,
  validationTime: "2026-07-16T23:55:00Z",
  syncMode: "delta",
  wallMs: 732000,
  artifactPaths: {
    "report.json": "/data/runs/run_0002/report.json",
    "run-summary.json": "/data/runs/run_0002/run-summary.json",
  },
  counts: {
    publicationPoints: 4,
    objects: 1284,
    rejectedObjects: 2,
    warnings: 3,
    trustAnchors: 5,
    vrps: 987,
    aspas: 12,
  },
  indexStatus: "ready",
};

export const RUN_1 = {
  ...RUN_2,
  runId: "run_0001",
  runSeq: 1,
  validationTime: "2026-07-15T23:50:00Z",
  syncMode: "snapshot",
  wallMs: 1290000,
  artifactPaths: {
    "report.json": "/data/runs/run_0001/report.json",
    "run-summary.json": "/data/runs/run_0001/run-summary.json",
  },
  counts: { ...RUN_2.counts, objects: 1270, vrps: 981 },
};

export const RUNS = [RUN_2, RUN_1];

export const REPO_A = {
  repoId: "repo-a1b2c3d4e5f6",
  uri: "rsync://repo-a.example/ca1/",
  host: "repo-a.example",
  transport: "rrdp",
  publicationPoints: 2,
  objects: 900,
  rejectedObjects: 1,
  downloadBytes: 245_000_000,
  syncDurationMsTotal: 12_400,
  phases: { rrdp_snapshot: 1, rrdp_delta: 1 },
  terminalStates: { fresh: 2 },
};

export const REPO_B = {
  repoId: "repo-b2c3d4e5f6a7",
  uri: "rsync://repo-b.example/ca2/",
  host: "repo-b.example",
  transport: "rsync",
  publicationPoints: 1,
  objects: 300,
  rejectedObjects: 1,
  downloadBytes: 80_000_000,
  syncDurationMsTotal: 45_800,
  phases: { rsync: 1 },
  terminalStates: { cached: 1 },
};

export const REPO_C = {
  repoId: "repo-c3d4e5f6a7b8",
  uri: "rsync://repo-c.example/ca3/",
  host: "repo-c.example",
  transport: "rrdp",
  publicationPoints: 1,
  objects: 84,
  rejectedObjects: 0,
  downloadBytes: 9_000_000,
  syncDurationMsTotal: 3_100,
  phases: { rrdp_delta: 1 },
  terminalStates: { fresh: 1 },
};

// Deliberately not in object-count order: index order (300, 900, 84) differs
// from `sort=objects&order=desc` (900, 300, 84) so tests can tell them apart.
export const REPOS = [REPO_B, REPO_A, REPO_C];

export const PP_1 = {
  ppId: "node_1",
  repoId: REPO_A.repoId,
  nodeId: 1,
  rsyncBaseUri: "rsync://repo-a.example/ca1/",
  manifestRsyncUri: "rsync://repo-a.example/ca1/manifest.mft",
  publicationPointRsyncUri: "rsync://repo-a.example/ca1/",
  rrdpNotificationUri: "https://repo-a.example/notification.xml",
  source: "rrdp",
  repoSyncSource: "rrdp",
  repoSyncPhase: "rrdp_delta",
  repoSyncDurationMs: 1200,
  repoSyncError: null,
  repoTerminalState: "fresh",
  thisUpdate: "2026-07-16T23:00:00Z",
  nextUpdate: "2026-07-17T23:00:00Z",
  objects: 610,
  rejectedObjects: 1,
  warnings: 2,
};

export const PP_2 = {
  ...PP_1,
  ppId: "node_2",
  nodeId: 2,
  manifestRsyncUri: "rsync://repo-a.example/ca1b/manifest.mft",
  publicationPointRsyncUri: "rsync://repo-a.example/ca1b/",
  objects: 290,
  rejectedObjects: 0,
  warnings: 1,
};

export const PP_3 = {
  ...PP_1,
  ppId: "node_3",
  nodeId: 3,
  repoId: REPO_B.repoId,
  manifestRsyncUri: "rsync://repo-b.example/ca2/manifest.mft",
  publicationPointRsyncUri: "rsync://repo-b.example/ca2/",
  rrdpNotificationUri: null,
  source: "rsync",
  repoSyncSource: "rsync",
  repoSyncPhase: "rsync",
  repoTerminalState: "cached",
  objects: 300,
  rejectedObjects: 1,
  warnings: 0,
};

export const PPS = [PP_1, PP_2, PP_3];

const SHA = (ch: string) => ch.repeat(64);

export const OBJ_ROA = {
  objectInstanceId: "obj-roa-0001",
  uri: "rsync://repo-a.example/ca1/alice.roa",
  sha256: SHA("a"),
  objectType: "roa",
  result: "ok",
  detailSummary: null,
  repoId: REPO_A.repoId,
  ppId: PP_1.ppId,
  sourceSection: "fresh",
  rejected: false,
  rejectReason: null,
};

export const OBJ_MFT = {
  objectInstanceId: "obj-mft-0001",
  uri: "rsync://repo-a.example/ca1/manifest.mft",
  sha256: SHA("b"),
  objectType: "manifest",
  result: "ok",
  detailSummary: null,
  repoId: REPO_A.repoId,
  ppId: PP_1.ppId,
  sourceSection: "fresh",
  rejected: false,
  rejectReason: null,
};

export const OBJ_CER_REJECTED = {
  objectInstanceId: "obj-cer-0001",
  uri: "rsync://repo-a.example/ca1/stale.cer",
  sha256: SHA("c"),
  objectType: "certificate",
  result: "error",
  detailSummary: "certificate expired: notAfter 2026-01-01T00:00:00Z",
  repoId: REPO_A.repoId,
  ppId: PP_1.ppId,
  sourceSection: "cached",
  rejected: true,
  rejectReason: "certificate expired: notAfter 2026-01-01T00:00:00Z",
};

export const OBJ_ASPA = {
  objectInstanceId: "obj-asa-0001",
  uri: "rsync://repo-b.example/ca2/bob.asa",
  sha256: SHA("d"),
  objectType: "aspa",
  result: "ok",
  detailSummary: null,
  repoId: REPO_B.repoId,
  ppId: PP_3.ppId,
  sourceSection: "cached",
  rejected: false,
  rejectReason: null,
};

export const OBJ_ROA_REJECTED = {
  objectInstanceId: "obj-roa-0002",
  uri: "rsync://repo-b.example/ca2/broken.roa",
  sha256: SHA("e"),
  objectType: "roa",
  result: "error",
  detailSummary: "manifest stale: thisUpdate in the past",
  repoId: REPO_B.repoId,
  ppId: PP_3.ppId,
  sourceSection: "cached",
  rejected: true,
  rejectReason: "manifest stale: thisUpdate in the past",
};

export const OBJ_CRL = {
  objectInstanceId: "obj-crl-0001",
  uri: "rsync://repo-a.example/ca1/main.crl",
  sha256: SHA("f"),
  objectType: "crl",
  result: "ok",
  detailSummary: null,
  repoId: REPO_A.repoId,
  ppId: PP_1.ppId,
  sourceSection: "fresh",
  rejected: false,
  rejectReason: null,
};

export const OBJECTS = [OBJ_ROA, OBJ_MFT, OBJ_CER_REJECTED, OBJ_ASPA, OBJ_ROA_REJECTED, OBJ_CRL];

export const STATS_VALIDATION = { ok: 1279, error: 2, skipped: 3 };
export const STATS_OBJECT_TYPES = {
  roa: 640,
  manifest: 4,
  crl: 4,
  certificate: 620,
  aspa: 12,
  gbr: 4,
};
export const STATS_REASONS = {
  "certificate expired: notAfter 2026-01-01T00:00:00Z": 1,
  "manifest stale: thisUpdate in the past": 1,
  "manifest is not valid at validation_time: this_update=2023-01-01T00:00:00Z": 3,
  "manifest is not valid at validation_time: this_update=2024-06-01T00:00:00Z": 2,
};
export const STATS_OVERVIEW = {
  publicationPoints: 4,
  objects: 1284,
  repos: REPOS.length,
  vrps: 987,
  aspas: 12,
};

export const ROA_PROJECTION = {
  schemaVersion: 2,
  sha256: SHA("a"),
  objectType: "roa",
  parseStatus: "ok",
  // Mirrors the live query service shape:
  //   projection = { input, object: { type, roa|manifest|… }, schemaVersion, tool }
  projection: {
    input: {
      type: "roa",
      path: "rsync://repo-a.example/ca1/alice.roa",
      bytes: { len: 1280, sha256: SHA("a") },
    },
    object: {
      type: "roa",
      roa: {
        asId: 65001,
        ipAddressFamilies: [
          {
            afi: "ipv4",
            addresses: [
              { prefix: "203.0.113.0/24", maxLength: 24 },
              { prefix: "198.51.100.0/25", maxLength: 25 },
            ],
          },
          {
            afi: "ipv6",
            addresses: [{ prefix: "2001:db8::/32", maxLength: 48 }],
          },
        ],
      },
      // CMS wrapper with the embedded EE certificate (real query service shape).
      signedObject: {
        signedData: {
          certificates: [
            {
              resourceCertificate: {
                kind: "Ee",
                version: 3,
                serialNumberHex: "0E65A501",
                issuer: "CN=A9114E750000, serialNumber=5A179648",
                subject: "CN=alice-roa-ee, serialNumber=0E65A501",
                validity: { notBefore: "2026-07-23T00:30:06Z", notAfter: "2027-01-01T00:00:00Z" },
                signatureAlgorithm: "1.2.840.113549.1.1.11",
                extensions: {
                  subjectKeyIdentifier: "aa11bb22cc33dd44ee55ff66778899aabbccdd",
                  authorityKeyIdentifier: "5a179648b3ef2369dce7bdb58140ff7dc7060abf",
                  ipResources: {
                    families: [
                      {
                        afi: "Ipv4",
                        choice: {
                          AddressesOrRanges: [
                            { Prefix: { addr: [203, 0, 113, 0], afi: "Ipv4", prefix_len: 24 } },
                          ],
                        },
                      },
                    ],
                  },
                  asResources: {
                    asnum: { AsIdsOrRanges: [{ Id: 65001 }] },
                  },
                },
              },
            },
          ],
        },
      },
    },
    schemaVersion: 2,
    tool: "rpki",
  },
};

export const MFT_PROJECTION = {
  schemaVersion: 2,
  sha256: SHA("b"),
  objectType: "mft",
  parseStatus: "ok",
  projection: {
    input: {
      type: "mft",
      path: "rsync://repo-a.example/ca1/manifest.mft",
      bytes: { len: 2048, sha256: SHA("b") },
    },
    object: {
      type: "mft",
      manifest: {
        manifestNumberHex: "0A2F",
        thisUpdate: "2026-07-16T23:00:00Z",
        nextUpdate: "2026-07-17T23:00:00Z",
        fileHashAlg: "sha256",
        fileCount: 3,
      },
    },
    schemaVersion: 2,
    tool: "rpki",
  },
};

export const MFT_FILES = [
  { fileName: "alice.roa", hashHex: SHA("a") },
  { fileName: "manifest.mft", hashHex: SHA("b") },
  { fileName: "stale.cer", hashHex: SHA("c") },
];

// Certificate projection in the real nested API shape:
// certificate payload under `object.resourceCertificate`, SKI/AKI/SIA/AIA/CRLDP
// and IP/AS resources under `extensions`.
export const CER_PROJECTION = {
  schemaVersion: 2,
  sha256: SHA("c"),
  objectType: "cer",
  parseStatus: "ok",
  projection: {
    input: {
      type: "cer",
      path: "rsync://repo-a.example/ca1/stale.cer",
      bytes: { len: 1534, sha256: SHA("c") },
    },
    object: {
      type: "cer",
      decode: { profileValid: true },
      resourceCertificate: {
        kind: "Ca",
        version: 3,
        serialNumberHex: "02C6C7",
        issuer: "CN=A90DC5BE, serialNumber=0E65A4F5",
        subject: "CN=A9114E750000, serialNumber=5A179648",
        validity: { notBefore: "2026-07-23T00:30:06Z", notAfter: "2027-09-30T00:00:00Z" },
        signatureAlgorithm: "1.2.840.113549.1.1.11",
        extensions: {
          subjectKeyIdentifier: "5a179648b3ef2369dce7bdb58140ff7dc7060abf",
          authorityKeyIdentifier: "0e65a4f5fd36b5bd68eb3c923408978c907aa79f",
          basicConstraintsCa: true,
          subjectInfoAccess: {
            accessDescriptions: [
              { accessMethodOid: "1.3.6.1.5.5.7.48.5", accessLocation: "rsync://repo-a.example/ca1/" },
            ],
          },
          caIssuersUris: ["rsync://repo-a.example/ca1/issuer.cer"],
          crlDistributionPointsUris: ["rsync://repo-a.example/ca1/main.crl"],
          ipResources: {
            families: [
              {
                afi: "Ipv4",
                choice: {
                  AddressesOrRanges: [
                    { Prefix: { addr: [103, 152, 34, 0], afi: "Ipv4", prefix_len: 23 } },
                    { Range: { min: { addr: [192, 0, 2, 0] }, max: { addr: [192, 0, 2, 255] } } },
                  ],
                },
              },
              {
                afi: "Ipv6",
                choice: {
                  AddressesOrRanges: [
                    {
                      Prefix: {
                        addr: [38, 6, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                        afi: "Ipv6",
                        prefix_len: 32,
                      },
                    },
                  ],
                },
              },
            ],
          },
          asResources: {
            asnum: {
              // 15 entries (> 12 collapsed limit) to exercise the "+N more" expand toggle.
              AsIdsOrRanges: [
                { Id: 38008 },
                { Id: 38023 },
                { Range: { min: 65536, max: 65551 } },
                { Id: 64496 },
                { Id: 64497 },
                { Id: 64498 },
                { Id: 64499 },
                { Id: 64500 },
                { Id: 64501 },
                { Id: 64502 },
                { Id: 64503 },
                { Id: 64504 },
                { Id: 64505 },
                { Id: 64506 },
                { Id: 64507 },
              ],
            },
          },
        },
      },
    },
    schemaVersion: 2,
    tool: "rpki",
  },
};

// CRL projection in the real nested API shape: CRL fields sit directly on the
// typed payload (no `crl` wrapper); crlNumber/AKI live under `extensions`.
export const CRL_PROJECTION = {
  schemaVersion: 2,
  sha256: SHA("f"),
  objectType: "crl",
  parseStatus: "ok",
  projection: {
    input: {
      type: "crl",
      path: "rsync://repo-a.example/ca1/main.crl",
      bytes: { len: 900, sha256: SHA("f") },
    },
    object: {
      type: "crl",
      decode: { profileValid: true },
      issuer: "CN=A9114E750000, serialNumber=5A179648",
      thisUpdate: "2026-07-23T02:47:00Z",
      nextUpdate: "2026-07-24T02:52:00Z",
      signatureAlgorithm: "1.2.840.113549.1.1.11",
      extensions: {
        authorityKeyIdentifier: "5a179648b3ef2369dce7bdb58140ff7dc7060abf",
        crlNumber: 3394,
        crlNumberHex: "0D42",
      },
      revokedCertificates: {
        count: 2,
        entries: [
          { serialNumberHex: "1B0B0AD86D78E77D1491B5069E6287D08EEA7C17", revocationDate: "2027-02-13T13:22:01Z" },
          { serialNumberHex: "6A106263F88133615B7E8D3466C192CEC0904F2D", revocationDate: "2027-03-18T19:58:00Z" },
        ],
      },
    },
    schemaVersion: 2,
    tool: "rpki",
  },
};

export const CRL_REVOKED = [
  { serialNumberHex: "1B0B0AD86D78E77D1491B5069E6287D08EEA7C17", revocationDate: "2027-02-13T13:22:01Z" },
  { serialNumberHex: "6A106263F88133615B7E8D3466C192CEC0904F2D", revocationDate: "2027-03-18T19:58:00Z" },
];

export const VALIDATION_SUMMARY = {
  finalStatus: "valid",
  auditResult: "ok",
  detailSummary: null,
  parsevalidate: { status: "ok", issues: [] },
  chainvalidate: { status: "ok", issues: [] },
};

export const EXPLAIN_RECORD = {
  finalStatus: "valid",
  auditResult: "ok",
  authoritative: false,
  explainMode: "audit_projection",
  parsevalidate: { status: "ok", issues: [] },
  chainvalidate: { status: "ok", mode: "audit_projection", issues: [], edgesCount: 2 },
  chainEdges: [],
};

export const CHAIN_EDGES = [
  {
    relation: "issued_by",
    fromUri: "rsync://repo-a.example/ca1/alice.roa",
    toUri: "rsync://repo-a.example/ca1/ca-certificate.cer",
    toObjectInstanceId: "obj-cer-0002",
    toSha256: SHA("f"),
    status: "linked",
  },
  {
    relation: "listed_in",
    fromUri: "rsync://repo-a.example/ca1/alice.roa",
    toUri: "rsync://repo-a.example/ca1/manifest.mft",
    toObjectInstanceId: "obj-mft-0001",
    toSha256: SHA("b"),
    status: "linked",
  },
];

export const HEALTH = {
  status: "ok",
  service: "rpki_query_service",
  version: 1,
  latestReadyRun: "run_0002",
};

export const SERVICE_INFO = { service: "rpki_query_service", version: 1 };

/**
 * VRP lookup fixtures (backend feature #122). 61 rows match `ip=81.68.1.1`
 * so the UI's 50-row page size paginates; the /16 row exercises covering
 * semantics for prefix queries, the IPv6 row exercises the second family.
 */
export const VRPS = [
  { runId: "run_0002", asn: 45090, prefix: "81.68.0.0/14", maxLength: 14 },
  { runId: "run_0002", asn: 64496, prefix: "81.68.0.0/16", maxLength: 24 },
  ...Array.from({ length: 59 }, (_, i) => ({
    runId: "run_0002",
    asn: 64512 + i,
    prefix: "81.68.0.0/14",
    maxLength: 14,
  })),
  { runId: "run_0002", asn: 0, prefix: "2001:7fa:0:1::/64", maxLength: 64 },
];
