import { mkdtemp, rm, mkdir } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import { ErrorCode } from "@pocketcoder/shared/constants";
import { openDatabase, closeDatabase } from "../../db/database.js";
import { createProject } from "../../db/repositories/projects.js";
// Suppress logger output in tests
vi.mock("../../utils/logger.js", () => ({
    logger: {
        debug: vi.fn(),
        info: vi.fn(),
        warn: vi.fn(),
        error: vi.fn(),
    },
}));
// Mock node-pty
const mockOnData = vi.fn();
const mockOnExit = vi.fn();
const mockWrite = vi.fn();
const mockResize = vi.fn();
const mockKill = vi.fn();
const mockSpawn = vi.fn().mockReturnValue({
    pid: 12345,
    onData: mockOnData,
    onExit: mockOnExit,
    write: mockWrite,
    resize: mockResize,
    kill: mockKill,
});
vi.mock("node-pty", () => ({
    spawn: (...args) => mockSpawn(...args),
}));
// Mock terminal-sessions DB calls
vi.mock("../../db/repositories/terminal-sessions.js", () => ({
    createTerminalSession: vi.fn().mockReturnValue({
        terminal_id: "mock-terminal-id",
        project_id: "mock-project-id",
        pid: 12345,
        created_at: "2026-02-20T00:00:00.000Z",
        closed_at: null,
    }),
    closeTerminalSession: vi.fn(),
}));
import { handleTerminalStdin } from "../terminal-stdin.js";
import { createTerminal, setTerminalSendFn } from "../../services/terminal-manager.js";
describe("terminal_stdin handler", () => {
    let tempDir;
    let projectDir;
    let dbPath;
    let projectId;
    let terminalId;
    beforeEach(async () => {
        vi.clearAllMocks();
        tempDir = await mkdtemp(join(tmpdir(), "pocketcoder-terminal-stdin-test-"));
        projectDir = join(tempDir, "project");
        dbPath = join(tempDir, "daemon.db");
        await mkdir(projectDir);
        closeDatabase();
        openDatabase(dbPath);
        const project = createProject("test-project", projectDir);
        projectId = project.project_id;
        // Set up terminal send function
        setTerminalSendFn(vi.fn());
        // Create a terminal for testing stdin
        terminalId = createTerminal(projectId, projectDir);
    });
    afterEach(async () => {
        closeDatabase();
        await rm(tempDir, { recursive: true, force: true });
    });
    function createRequest(overrides) {
        return {
            type: "terminal_stdin",
            requestId: "req-1",
            sessionId: projectId,
            payload: {
                terminalId,
                data: "hello\n",
                ...overrides,
            },
        };
    }
    function createSendCollector() {
        const responses = [];
        const send = (msg) => {
            responses.push(msg);
        };
        return { responses, send };
    }
    it("should write data to PTY", async () => {
        const { responses, send } = createSendCollector();
        await handleTerminalStdin(createRequest(), send);
        expect(mockWrite).toHaveBeenCalledOnce();
        expect(mockWrite).toHaveBeenCalledWith("hello\n");
        // No response on success (fire-and-forget)
        expect(responses).toHaveLength(0);
    });
    it("should return error for invalid terminal", async () => {
        const { responses, send } = createSendCollector();
        await handleTerminalStdin(createRequest({ terminalId: "non-existent-terminal", data: "hello" }), send);
        expect(responses).toHaveLength(1);
        expect(responses[0].error.code).toBe(ErrorCode.TERMINAL_NOT_FOUND);
    });
    it("should handle binary/escape sequences", async () => {
        const { responses, send } = createSendCollector();
        // ANSI escape: clear screen + tab + carriage return
        const data = "\x1b[2J\t\r";
        await handleTerminalStdin(createRequest({ data }), send);
        expect(mockWrite).toHaveBeenCalledWith(data);
        expect(responses).toHaveLength(0);
    });
    it("should handle empty data", async () => {
        const { responses, send } = createSendCollector();
        await handleTerminalStdin(createRequest({ data: "" }), send);
        expect(mockWrite).toHaveBeenCalledWith("");
        expect(responses).toHaveLength(0);
    });
    it("should include requestId in error response", async () => {
        const { responses, send } = createSendCollector();
        const request = createRequest({ terminalId: "bad-id", data: "test" });
        request.requestId = "req-42";
        await handleTerminalStdin(request, send);
        expect(responses).toHaveLength(1);
        expect(responses[0].requestId).toBe("req-42");
    });
});
//# sourceMappingURL=terminal-stdin.test.js.map