import { describe, expect, it, vi } from "vitest";
import type {
  JsonValue,
  PluginPropertyScalar,
} from "@thortiq/plugin-api";
import type { SandboxControllerApiV1 } from "@thortiq/plugin-sdk/sandbox";
import { runCsvFromSandbox } from "../src/activate.js";

function fixture(confirm: boolean) {
  const csv = "id,name\r\nA,Ada Synthetic\r\n";
  const csvBytes = Uint8Array.from(csv, character => character.charCodeAt(0));
  const writes = vi.fn(async operations => operations.map(
    (operation: { readonly id: string }) => ({
      id: operation.id,
      status: "updated",
      propertiesRevision: "properties-next",
    }),
  ));
  const settings: Readonly<Record<string, JsonValue>> = {
    csvPath: "imports/synthetic.csv",
    encoding: "auto",
    delimiter: "comma",
    headerMode: "present",
    noteIdentityProperty: "ExternalId",
    csvIdentityField: "id",
    identityType: "string",
    mappings: "name=ImportedName",
    watchForChanges: false,
    autoApply: false,
  };
  const api = {
    assets: {
      async list() {
        return {
          assets: [{
            path: "imports/synthetic.csv",
            mediaType: "text/csv",
            sizeBytes: csvBytes.byteLength,
            updatedAt: "2026-01-01T00:00:00.000Z",
          }],
          total: 1,
          cursor: null,
        };
      },
      async readBytes() {
        return csvBytes;
      },
    },
    metadata: {
      async findByPropertyValues(request: {
        readonly values: readonly PluginPropertyScalar[];
      }) {
        return {
          rows: request.values.map(value => ({
            value,
            matches: [{
              id: "synthetic-note",
              title: "Synthetic note",
              path: "notes/synthetic.md",
              values: { ExternalId: value, ImportedName: "Old" },
              propertiesRevision: "properties-1",
              updatedAt: "2026-01-01T00:00:00.000Z",
            }],
          })),
          missingValues: [],
          cursor: null,
        };
      },
    },
    notes: { updatePropertiesBatch: writes },
    settings: {
      async get(key: string) {
        return settings[key] ?? null;
      },
    },
    storage: { local: { set: vi.fn() } },
    dialogs: { confirm: vi.fn(async () => confirm) },
  } as unknown as SandboxControllerApiV1;
  return { api, writes };
}

describe("sandboxed-page CSV workflow adapter", () => {
  it("reads through the asset broker and writes only after confirmation", async () => {
    const signal = new AbortController().signal;
    const cancelled = fixture(false);
    const cancelledStatus = await runCsvFromSandbox(cancelled.api, "manual", signal);
    expect(cancelledStatus).toMatchObject({ outcome: "cancelled", counts: { proposed: 1 } });
    expect(cancelled.writes).not.toHaveBeenCalled();

    const accepted = fixture(true);
    await expect(runCsvFromSandbox(accepted.api, "manual", signal))
      .resolves.toMatchObject({ outcome: "applied", counts: { updated: 1 } });
    expect(accepted.writes).toHaveBeenCalledOnce();
  });
});
