import { beforeEach, describe, expect, it } from "vitest";
import type { ClientSummary, DevAuditLog } from "../../lib/devApi";
import {
  buildRecentClientChangeDetails,
  buildRecentClientChanges,
  getRecentClientActionLabel,
} from "./recentClientChanges";

function makeClient(id: string, name = id): ClientSummary {
  return {
    id,
    name,
    type: "private",
    status: "active",
    createdAt: "2026-05-27T00:00:00.000Z",
    redirectUris: [],
    scopes: [],
  };
}

function makeAuditLog(
  eventId: string,
  timestamp: string,
  action: string,
  targetId: string,
  details: Record<string, unknown>,
): DevAuditLog {
  return {
    event_id: eventId,
    timestamp,
    user_id: "actor-1",
    event_type: "AUDIT",
    status: "success",
    ip_address: "127.0.0.1",
    user_agent: "vitest",
    details: JSON.stringify({
      action,
      target_id: targetId,
      ...details,
    }),
  };
}

describe("recent client changes", () => {
  beforeEach(() => {
    window.localStorage.clear();
    window.history.replaceState({}, "", "/");
  });

  function mockLocale(locale: "ko" | "en") {
    window.localStorage.clear();
    window.history.replaceState({}, "", `/${locale}`);
  }

  it("translates action labels and relation details by locale", () => {
    mockLocale("en");

    expect(getRecentClientActionLabel("CREATE_CLIENT")).toBe("App creation");
    expect(getRecentClientActionLabel("UPDATE_CLIENT")).toBe(
      "Settings changes",
    );
    expect(getRecentClientActionLabel("UPDATE_CLIENT_STATUS")).toBe(
      "Status changes",
    );
    expect(getRecentClientActionLabel("ROTATE_SECRET")).toBe(
      "Client secret rotation",
    );
    expect(getRecentClientActionLabel("ADD_RELATION")).toBe("Add Relationship");
    expect(getRecentClientActionLabel("REMOVE_RELATION")).toBe(
      "Remove Relationship",
    );
    expect(getRecentClientActionLabel("DELETE_CLIENT")).toBe("App deletion");
    expect(getRecentClientActionLabel("OTHER_ACTION")).toBe("OTHER_ACTION");

    expect(
      buildRecentClientChangeDetails("ROTATE_SECRET", {
        after: {},
      }),
    ).toEqual([{ label: "Client Secret", value: "Secret Rotated" }]);

    expect(
      buildRecentClientChangeDetails("ADD_RELATION", {
        after: {
          relation: "admins",
          subject: "User:1",
        },
      }),
    ).toEqual([
      { label: "Relation", value: "admins" },
      { label: "Subject", value: "User:1" },
    ]);
  });

  it("builds recent client changes with sorting, filtering, and detail slicing", () => {
    mockLocale("ko");

    const clients = [
      makeClient("client-a", "Alpha"),
      makeClient("client-b", ""),
    ];
    const auditLogs = [
      makeAuditLog(
        "evt-1",
        "2026-05-27T07:00:00.000Z",
        "CREATE_CLIENT",
        "client-a",
        {
          after: { name: "Alpha", type: "private", status: "active" },
        },
      ),
      makeAuditLog(
        "evt-2",
        "2026-05-27T08:00:00.000Z",
        "UPDATE_CLIENT",
        "client-a",
        {
          before: {
            name: "Alpha old",
            status: "inactive",
            sameField: "same",
            oldField: "old-value",
          },
          after: {
            name: "Alpha new",
            status: "active",
            sameField: "same",
            newField: "new-value",
          },
        },
      ),
      makeAuditLog(
        "evt-3",
        "2026-05-27T09:00:00.000Z",
        "UPDATE_CLIENT_STATUS",
        "client-a",
        {
          before: { status: "inactive" },
          after: { status: "active" },
        },
      ),
      makeAuditLog(
        "evt-4",
        "2026-05-27T10:00:00.000Z",
        "ADD_RELATION",
        "client-b",
        {
          after: {
            relation: "audit_viewer",
            subject: "User:89692983-f512-4d96-845d-ac6123d08b95",
          },
        },
      ),
      makeAuditLog(
        "evt-5",
        "2026-05-27T11:00:00.000Z",
        "REMOVE_RELATION",
        "client-b",
        {
          before: {
            relation: "admins",
            subject: "User:89692983-f512-4d96-845d-ac6123d08b95",
          },
        },
      ),
      makeAuditLog(
        "evt-6",
        "2026-05-27T12:00:00.000Z",
        "ROTATE_SECRET",
        "client-a",
        {
          after: {},
        },
      ),
      makeAuditLog(
        "evt-7",
        "2026-05-27T13:00:00.000Z",
        "DELETE_CLIENT",
        "client-a",
        {
          before: {
            name: "Alpha",
            status: "inactive",
          },
        },
      ),
      makeAuditLog(
        "evt-8",
        "2026-05-27T14:00:00.000Z",
        "UNSUPPORTED_ACTION",
        "client-a",
        {
          after: { name: "Ignored" },
        },
      ),
    ];

    const changes = buildRecentClientChanges(auditLogs, clients);

    expect(changes).toHaveLength(7);
    expect(changes[0]).toMatchObject({
      eventId: "evt-7",
      clientName: "Alpha",
      actionLabel: "앱 삭제",
    });
    expect(changes[1]).toMatchObject({
      eventId: "evt-6",
      clientName: "Alpha",
      actionLabel: "클라이언트 시크릿 재발급",
      detailLabels: [
        {
          label: "클라이언트 시크릿",
          value: "Client Secret이 재발급되었습니다.",
        },
      ],
    });
    expect(changes[2]).toMatchObject({
      eventId: "evt-5",
      clientName: "client-b",
      actionLabel: "관계 삭제",
      detailLabels: [
        { label: "관계", value: "admins" },
        {
          label: "주체",
          value: "User:89692983-f512-4d96-845d-ac6123d08b95",
        },
      ],
    });
    expect(changes[4]).toMatchObject({
      eventId: "evt-3",
      actionLabel: "상태 변경",
      clientName: "Alpha",
      detailLabels: [{ value: "inactive → active" }],
    });
    expect(changes[5]).toMatchObject({
      eventId: "evt-2",
      actionLabel: "설정 변경",
      detailLabels: [
        { label: "애플리케이션", value: "Alpha old → Alpha new" },
        { label: "상태", value: "inactive → active" },
        { label: "oldField", value: "old-value" },
      ],
    });
    expect(changes[6]).toMatchObject({
      eventId: "evt-1",
      actionLabel: "앱 생성",
      detailLabels: [
        { label: "애플리케이션", value: "Alpha" },
        { label: "유형", value: "private" },
        { label: "상태", value: "active" },
      ],
    });
  });
});
