import { describe, expect, it } from "vitest";
import { authed, login, setup } from "../helpers.js";

// E2E は HTTP アプリ + scheduler/run を通して検証（DRY_RUN相当の本番モード=DryRunMailerをspyに利用）
describe("E2E シナリオ", () => {
  it("E2E-01 一斉配信（下書き→予約→承認→送信）", async () => {
    const { app, mailer, store } = setup({ cfg: { dryRun: false } });
    const cookie = await login(app);
    const list = (await (await app.request("/api/lists", authed(cookie, { name: "読者" }))).json()).list;
    for (const e of ["a@x.com", "b@x.com", "c@x.com"]) {
      await app.request("/api/subscribers", authed(cookie, { email: e, listId: list.id }));
    }
    const bc = (await (await app.request("/api/broadcasts", authed(cookie, { name: "お知らせ", subject: "件名", body_html: "<p>本文</p>", list_id: list.id }))).json()).broadcast;
    await app.request(`/api/broadcasts/${bc.id}/approve`, authed(cookie));
    await app.request(`/api/broadcasts/${bc.id}/schedule`, authed(cookie, {}));
    const run = await (await app.request("/api/scheduler/run", authed(cookie))).json();
    expect(run.summary.broadcastSends).toBe(3);
    expect((await store.getBroadcast(bc.id))?.status).toBe("sent");
    // 本文に配信停止リンクが含まれる
    expect((mailer as any).sent[0].msg.html).toContain("/u/");
  });

  it("E2E-03 外部連携で登録→ステップ自動開始", async () => {
    const { app, mailer } = setup({ cfg: { dryRun: false } });
    const cookie = await login(app);
    const list = (await (await app.request("/api/lists", authed(cookie, { name: "L" }))).json()).list;
    const camp = (await (await app.request("/api/campaigns", authed(cookie, { name: "講座", list_id: list.id }))).json()).campaign;
    await app.request(`/api/campaigns/${camp.id}/steps`, authed(cookie, { step_order: 0, delay_minutes: 0, subject: "1通目", body_html: "<p>ようこそ</p>" }));
    const hook = (await (await app.request("/api/hooks", authed(cookie, { list_id: list.id, campaign_id: camp.id, name: "LP" }))).json()).hook;

    // 外部ツールがWebhookを叩く
    await app.request(`/api/hooks/${hook.token}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email: "lead@x.com" }) });
    const run = await (await app.request("/api/scheduler/run", authed(cookie))).json();
    expect(run.summary.stepSends).toBe(1);
    expect((mailer as any).sent[0].msg.to).toBe("lead@x.com");
  });

  it("E2E-02 ステップメールが遅延に従い進行", async () => {
    const { app, mailer, clock } = setup({ cfg: { dryRun: false } });
    const cookie = await login(app);
    const list = (await (await app.request("/api/lists", authed(cookie, { name: "L" }))).json()).list;
    const camp = (await (await app.request("/api/campaigns", authed(cookie, { name: "C", list_id: list.id }))).json()).campaign;
    await app.request(`/api/campaigns/${camp.id}/steps`, authed(cookie, { step_order: 0, delay_minutes: 0, subject: "S0", body_html: "0" }));
    await app.request(`/api/campaigns/${camp.id}/steps`, authed(cookie, { step_order: 1, delay_minutes: 60, subject: "S1", body_html: "1" }));
    await app.request(`/api/campaigns/${camp.id}/enroll`, authed(cookie, { email: "u@x.com" }));

    await app.request("/api/scheduler/run", authed(cookie)); // step0
    expect((mailer as any).sent.length).toBe(1);
    await app.request("/api/scheduler/run", authed(cookie)); // まだstep1来ない
    expect((mailer as any).sent.length).toBe(1);
    clock.advanceMinutes(60);
    await app.request("/api/scheduler/run", authed(cookie)); // step1
    expect((mailer as any).sent.length).toBe(2);
  });

  it("E2E-05 未承認では誤送信しない", async () => {
    const { app, mailer } = setup({ cfg: { dryRun: false } });
    const cookie = await login(app);
    const list = (await (await app.request("/api/lists", authed(cookie, { name: "L" }))).json()).list;
    await app.request("/api/subscribers", authed(cookie, { email: "a@x.com", listId: list.id }));
    const bc = (await (await app.request("/api/broadcasts", authed(cookie, { name: "B", subject: "S", body_html: "x", list_id: list.id }))).json()).broadcast;
    await app.request(`/api/broadcasts/${bc.id}/schedule`, authed(cookie, {})); // 承認せず予約
    const run = await (await app.request("/api/scheduler/run", authed(cookie))).json();
    expect(run.summary.broadcastSends).toBe(0);
    expect((mailer as any).sent.length).toBe(0);
  });
});
