import { ReadableLogRecord } from "@opentelemetry/sdk-logs";
import { ResourceMetrics } from "@opentelemetry/sdk-metrics";
import { ReadableSpan } from "@opentelemetry/sdk-trace-base";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { PIIExporterDecorator } from "../../lib/exporter/pii-exporter-decorator";

describe("PIIExporterDecorator", () => {
  let exporterMock: any;
  let config: any;
  let piiExporter: PIIExporterDecorator;

  beforeEach(() => {
    exporterMock = {
      export: vi.fn(),
      shutdown: vi.fn(() => Promise.resolve()),
      forceFlush: vi.fn(() => Promise.resolve()),
      _delegate: {},
    };

    config = { detection: { email: true } };
    piiExporter = new PIIExporterDecorator(exporterMock, config);
  });

  it("should redact emails in span name and attributes", () => {
    const items: ReadableSpan[] = [
      {
        name: "user@example.com",
        kind: 0,
        spanContext: () => ({}),
        attributes: { email: "user@example.com" },
        resource: { attributes: { owner: "user@example.com" } },
        events: [
          {
            name: "Login from user@example.com",
            attributes: { email: "user@example.com" },
          },
        ],
      } as any,
    ];

    const callback = vi.fn();
    piiExporter.export(items, callback);

    const exportedSpan = exporterMock.export.mock.calls[0][0][0];
    expect(exportedSpan.name).toBe("[REDACTED EMAIL]");
    expect(exportedSpan.attributes.email).toBe("[REDACTED EMAIL]");
    expect(exportedSpan.resource.attributes.owner).toBe("[REDACTED EMAIL]");
    expect(exportedSpan.events[0].name).toBe("Login from [REDACTED EMAIL]");
    expect(exportedSpan.events[0].attributes.email).toBe("[REDACTED EMAIL]");
  });

  it("should redact emails in log records", () => {
    const items: ReadableLogRecord[] = [
      {
        body: "Error from user@example.com",
        attributes: { email: "user@example.com" },
        severityText: "INFO",
        severityNumber: 1,
        resource: { attributes: { owner: "user@example.com" } },
      } as any,
    ];

    const callback = vi.fn();
    piiExporter.export(items, callback);

    const exportedLog = exporterMock.export.mock.calls[0][0][0];
    expect(exportedLog.body).toBe("Error from [REDACTED EMAIL]");
    expect(exportedLog.attributes.email).toBe("[REDACTED EMAIL]");
    expect(exportedLog.resource.attributes.owner).toBe("[REDACTED EMAIL]");
  });

  it("should redact emails in resource metrics", () => {
    const metrics: ResourceMetrics = {
      resource: {
        attributes: { maintainer: "user@example.com" },
      },
      scopeMetrics: [],
    } as any;

    const callback = vi.fn();
    piiExporter.export(metrics, callback);

    const exportedMetric = exporterMock.export.mock.calls[0][0];
    expect(exportedMetric.resource.attributes.maintainer).toBe(
      "[REDACTED EMAIL]",
    );
  });
});
