// src/tools/file/write.test.ts
// Copyright (C) 2025 DTP Technologies, LLC
// All Rights Reserved

import { describe, it, expect, beforeEach, afterEach } from "vitest";
import { FileWriteTool } from "./write.js";
import fs from "node:fs/promises";
import path from "node:path";
import { PROJECT_ROOT } from "../../config/env.js";

const tool = new FileWriteTool();

describe("FileWriteTool", () => {
  const testDir = path.join(PROJECT_ROOT, "test-temp-write");
  const testFile = path.join(testDir, "test.txt");

  beforeEach(async () => {
    await fs.mkdir(testDir, { recursive: true });
  });

  afterEach(async () => {
    await fs.rm(testDir, { recursive: true, force: true });
  });

  it("should have correct tool definition", () => {
    expect(tool.definition.function.name).toBe("file_write");
    expect(tool.definition.function.description).toContain(
      "Create a new file or overwrite",
    );
    const params = tool.definition.function.parameters as any;
    expect(params.required).toEqual(["path", "content"]);
  });

  it("should reject empty path", async () => {
    const result = await tool.execute({} as any, { content: "test" });
    expect(result).toContain("error");
    expect(result).toContain("MISSING_PARAMETER");
  });

  it("should reject undefined content", async () => {
    const result = await tool.execute({} as any, { path: "test.txt" });
    expect(result).toContain("error");
    expect(result).toContain("MISSING_PARAMETER");
  });

  it("should reject path traversal attempts", async () => {
    const result = await tool.execute({} as any, {
      path: "../../../etc/passwd",
      content: "test",
    });
    expect(result).toContain("error");
    expect(result).toContain("SECURITY_VIOLATION");
  });

  it("should create new file and return plain text response", async () => {
    const result = await tool.execute({} as any, {
      path: "test-temp-write/test.txt",
      content: "Hello, World!",
    });

    expect(result).not.toContain('"success"');
    expect(result).toContain("PATH:");
    expect(result).toContain("FILE OPERATION: write");
    expect(result).toContain("CREATED: true");
    expect(result).toContain("BYTES WRITTEN:");
    expect(result).toContain("---");
    expect(result).toContain("File written:");
  });

  it("should overwrite existing file and return plain text response", async () => {
    // Create file first
    await fs.writeFile(testFile, "original content");

    const result = await tool.execute({} as any, {
      path: "test-temp-write/test.txt",
      content: "new content",
    });

    expect(result).not.toContain('"success"');
    expect(result).toContain("PATH:");
    expect(result).toContain("FILE OPERATION: write");
    expect(result).toContain("CREATED: false");
    expect(result).toContain("BYTES WRITTEN:");
    expect(result).toContain("---");
  });

  it("should create parent directories automatically", async () => {
    const nestedPath = "test-temp-write/nested/deep/file.txt";
    const result = await tool.execute({} as any, {
      path: nestedPath,
      content: "nested content",
    });

    expect(result).toContain("File written:");
    const exists = await fs
      .access(path.join(PROJECT_ROOT, nestedPath))
      .then(() => true)
      .catch(() => false);
    expect(exists).toBe(true);
  });

  it("should return correct byte count", async () => {
    const content = "Hello, World!";
    const result = await tool.execute({} as any, {
      path: "test-temp-write/bytecount.txt",
      content: content,
    });

    const expectedBytes = Buffer.byteLength(content, "utf-8");
    expect(result).toContain(`BYTES WRITTEN: ${expectedBytes}`);
  });

  it("should handle multiline content", async () => {
    const content = "Line 1\nLine 2\nLine 3";
    const result = await tool.execute({} as any, {
      path: "test-temp-write/multiline.txt",
      content: content,
    });

    expect(result).toContain("File written:");
    const written = await fs.readFile(
      path.join(PROJECT_ROOT, "test-temp-write/multiline.txt"),
      "utf-8",
    );
    expect(written).toBe(content);
  });

  it("should handle empty content", async () => {
    const result = await tool.execute({} as any, {
      path: "test-temp-write/empty.txt",
      content: "",
    });

    expect(result).toContain("BYTES WRITTEN: 0");
    const written = await fs.readFile(
      path.join(PROJECT_ROOT, "test-temp-write/empty.txt"),
      "utf-8",
    );
    expect(written).toBe("");
  });

  it("should not return JSON format on success", async () => {
    const result = await tool.execute({} as any, {
      path: "test-temp-write/nojson.txt",
      content: "test",
    });

    // Should not contain JSON structure
    expect(result).not.toMatch(/^\s*\{/);
    expect(result).not.toContain('"success":');
    expect(result).not.toContain('"data":');
    expect(result).not.toContain('"message":');
  });
});
