import { describe, it, expect, beforeEach, afterEach } from "vitest";
import fs from "fs";
import os from "os";
import path from "path";
import { getHostingInfo, getAppStatus, getDeployErrors } from "../src/modules/hosting.js";

let tmpDir: string;

beforeEach(() => {
  tmpDir = path.join(os.tmpdir(), `treehouse-test-${Math.random().toString(36).slice(2)}`);
  fs.mkdirSync(tmpDir, { recursive: true });
  process.env.TENANT_ID = "test-tenant";
});

afterEach(() => {
  fs.rmSync(tmpDir, { recursive: true, force: true });
  delete process.env.TENANT_ID;
});

describe("getHostingInfo", () => {
  it("returns empty object when hosting.json is missing", async () => {
    const result = await getHostingInfo(tmpDir);
    expect(result).toEqual({});
  });

  it("returns parsed hosting.json", async () => {
    const data = { ports: [3000, 8080], domain: "test.example.com" };
    fs.writeFileSync(path.join(tmpDir, "hosting.json"), JSON.stringify(data));
    const result = await getHostingInfo(tmpDir);
    expect(result).toEqual(data);
  });
});

describe("getAppStatus", () => {
  it("returns empty array when hosting-status dir is missing", async () => {
    const result = await getAppStatus(undefined, tmpDir);
    expect(result).toEqual([]);
  });

  it("returns all app statuses when no app specified", async () => {
    const statusDir = path.join(tmpDir, "hosting-status");
    fs.mkdirSync(statusDir);
    fs.writeFileSync(path.join(statusDir, "myapp.json"), JSON.stringify({ app: "myapp", status: "running" }));
    fs.writeFileSync(path.join(statusDir, "otherapp.json"), JSON.stringify({ app: "otherapp", status: "stopped" }));
    const result = await getAppStatus(undefined, tmpDir);
    expect(result).toHaveLength(2);
  });

  it("returns single app status when app name specified", async () => {
    const statusDir = path.join(tmpDir, "hosting-status");
    fs.mkdirSync(statusDir);
    fs.writeFileSync(path.join(statusDir, "myapp.json"), JSON.stringify({ app: "myapp", status: "running" }));
    const result = await getAppStatus("myapp", tmpDir);
    expect(result).toHaveLength(1);
    expect(result[0].app).toBe("myapp");
  });

  it("returns empty array for missing app", async () => {
    const statusDir = path.join(tmpDir, "hosting-status");
    fs.mkdirSync(statusDir);
    const result = await getAppStatus("nonexistent", tmpDir);
    expect(result).toEqual([]);
  });
});

describe("getDeployErrors", () => {
  it("returns empty array when errors dir is missing", async () => {
    const result = await getDeployErrors(5, tmpDir);
    expect(result).toEqual([]);
  });

  it("returns errors sorted descending by filename", async () => {
    const errorsDir = path.join(tmpDir, "errors");
    fs.mkdirSync(errorsDir);
    fs.writeFileSync(path.join(errorsDir, "2024-01-01.json"), JSON.stringify({ error: "first" }));
    fs.writeFileSync(path.join(errorsDir, "2024-01-03.json"), JSON.stringify({ error: "third" }));
    fs.writeFileSync(path.join(errorsDir, "2024-01-02.json"), JSON.stringify({ error: "second" }));
    const result = await getDeployErrors(5, tmpDir);
    expect(result[0].error).toBe("third");
    expect(result[1].error).toBe("second");
    expect(result[2].error).toBe("first");
  });

  it("limits results to the specified count", async () => {
    const errorsDir = path.join(tmpDir, "errors");
    fs.mkdirSync(errorsDir);
    for (let i = 0; i < 10; i++) {
      fs.writeFileSync(path.join(errorsDir, `2024-01-0${i}.json`), JSON.stringify({ error: `error${i}` }));
    }
    const result = await getDeployErrors(3, tmpDir);
    expect(result).toHaveLength(3);
  });
});
