import { env } from "cloudflare:test";
import { describe, it, expect, beforeEach, vi } from "vitest";
import { StateStore } from "../src/stateStore";
import { createTicketForOutage, type TicketDeps } from "../src/handlers";
import type { SentryOutageIssue } from "../src/sentryClient";

const issue: SentryOutageIssue = {
  id: "44",
  title: "Downtime detected for https://puanbenim.com",
  permalink: "https://sentry/44/",
  status: "unresolved",
  firstSeen: "2026-06-18T02:00:00Z",
};

function ytStub() {
  return {
    createIssue: vi.fn(async (_project: string, _summary: string, _description: string) => ({ id: "2-9", idReadable: "PA-201" })),
    setAssignee: vi.fn(async () => {}),
  };
}

function deps(store: StateStore, yt: ReturnType<typeof ytStub>, now = 1000): TicketDeps {
  return {
    store,
    yt,
    hetzner: vi.fn(async () => ({ activeIncidents: [], summary: "Hetzner'da eşleşen aktif incident yok → muhtemelen bizim taraf" })),
    env,
    now: () => now,
  };
}

describe("createTicketForOutage", () => {
  let store: StateStore;
  beforeEach(async () => {
    store = new StateStore(env.OUTAGE_STATE);
    for (const k of (await env.OUTAGE_STATE.list()).keys) await env.OUTAGE_STATE.delete(k.name);
  });

  it("creates a ticket assigned to primary and stores an open record", async () => {
    const yt = ytStub();
    await createTicketForOutage(issue, deps(store, yt));
    expect(yt.createIssue).toHaveBeenCalledOnce();
    expect(yt.setAssignee).toHaveBeenCalledWith("2-9", env.ASSIGNEE_PRIMARY);
    const rec = await store.get("44");
    expect(rec?.ticketReadable).toBe("PA-201");
    expect(rec?.status).toBe("open");
    expect(rec?.sentryPermalink).toBe("https://sentry/44/");
    const desc = yt.createIssue.mock.calls[0][2] as string;
    expect(desc).toContain("sentry-issue-id: 44");
  });

  it("does not create a second ticket for the same outage (dedup)", async () => {
    const yt = ytStub();
    const d = deps(store, yt);
    await createTicketForOutage(issue, d);
    await createTicketForOutage(issue, d);
    expect(yt.createIssue).toHaveBeenCalledOnce();
  });

  it("marks hetznerMatched when a region-matched incident exists at creation", async () => {
    const yt = ytStub();
    const d = deps(store, yt);
    d.hetzner = vi.fn(async () => ({
      activeIncidents: [{ title: "nbg1 fault", link: "https://h/x", matchedRegion: true }],
      summary: "Muhtemel Hetzner kaynaklı: nbg1 fault",
    }));
    await createTicketForOutage(issue, d);
    expect((await store.get("44"))?.hetznerMatched).toBe(true);
  });

  it("leaves hetznerMatched false when no region match at creation", async () => {
    const yt = ytStub();
    await createTicketForOutage(issue, deps(store, yt));
    expect((await store.get("44"))?.hetznerMatched).toBe(false);
  });
});
