import { Cause, Effect, flow, Option } from "effect";

import { defineCommand } from "../commands.ts";
import { showErrorAndPromptLogs } from "../lib/showErrorAndPromptLogs.ts";
import { isProblematicFilename } from "../lib/validateNotebookFilename.ts";
import { VsCode } from "../platform/VsCode.ts";
import { Telemetry } from "../telemetry/Telemetry.ts";
import { MarimoCommands } from "./MarimoCommands.ts";

const handler = Effect.fn("command.newMarimoNotebook")(
  function* () {
    const code = yield* VsCode;
    const telemetry = yield* Telemetry;

    const uri = yield* code.window.showSaveDialog({
      filters: { Python: ["py"] },
    });

    if (Option.isNone(uri)) {
      return;
    }

    const validation = isProblematicFilename(uri.value);
    if (validation.problematic) {
      yield* code.window.showErrorMessage(validation.message, { modal: true });
      return;
    }

    yield* code.workspace.fs.writeFile(
      uri.value,
      new TextEncoder().encode(
        `import marimo

app = marimo.App()

@app.cell
def _():
    return
`.trim(),
      ),
    );

    const notebook = yield* code.workspace.openNotebookDocument(uri.value);
    yield* code.window.showNotebookDocument(notebook);

    yield* Effect.logInfo("Created new marimo notebook").pipe(
      Effect.annotateLogs({ uri: notebook.uri.toString() }),
    );

    yield* telemetry.notebookCreated();
  },
  flow(
    Effect.catchTag(
      "FileSystemError",
      Effect.fn(function* (error) {
        yield* Effect.logError("Failed to create notebook").pipe(
          Effect.annotateLogs({ cause: Cause.fail(error) }),
        );
        yield* showErrorAndPromptLogs("Failed to create notebook.");
      }),
    ),
  ),
);

export default defineCommand(MarimoCommands.newMarimoNotebook, handler);
