/**
 * Ma vérification du flux. On ouvre en tant qu'une personne, on déclenche
 * l'action d'une autre, on regarde arriver les octets, et on remet tout.
 */
import { eq, sql } from "drizzle-orm"

import { db } from "@/lib/db/client"
import { domainEvents, notifications, people, recurringTemplates, taskInstances, taskSubmissions } from "@/lib/db/schema"

const BASE = "http://127.0.0.1:4148"

async function signIn(username: string, password: string) {
  const r = await fetch(`${BASE}/api/auth/sign-in/username`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ username, password }),
  })
  const cookie = r.headers.getSetCookie().map((c) => c.split(";")[0]).join("; ")
  if (!r.ok) throw new Error(`${username}: ${r.status}`)
  return cookie
}

/** Ouvre le flux et rend une fonction qui donne ce qui est arrivé jusqu'ici. */
async function open(cookie: string, lastId?: string) {
  const chunks: { at: number; text: string }[] = []
  const started = Date.now()
  const controller = new AbortController()
  const res = await fetch(`${BASE}/api/notifications/stream`, {
    headers: { cookie, ...(lastId ? { "Last-Event-ID": lastId } : {}) },
    signal: controller.signal,
  })
  const reader = res.body!.getReader()
  const decoder = new TextDecoder()
  ;(async () => {
    try {
      while (true) {
        const { done, value } = await reader.read()
        if (done) break
        chunks.push({ at: Date.now() - started, text: decoder.decode(value) })
      }
    } catch {
      /* fermé */
    }
  })()
  return {
    status: res.status,
    type: res.headers.get("content-type"),
    chunks,
    close: () => controller.abort(),
  }
}

const nattikan = await signIn("nattikan", "staff1")
const narisara = await signIn("narisara", "staff2")
const narin = await signIn("narin", "admin1")

const cible = await open(nattikan)
const temoin = await open(narisara)
await new Promise((r) => setTimeout(r, 400))
console.log("flux ouvert :", { status: cible.status, type: cible.type })
console.log("avant l'acte, reçu :", cible.chunks.length, "morceaux")

// narin relance une tâche de nattikan.
const [task] = await db
  .select({ id: taskInstances.id })
  .from(taskInstances)
  .innerJoin(people, eq(people.id, taskInstances.assigneePersonId))
  .where(sql`${people.username} = 'nattikan' and ${taskInstances.status} in ('todo','started')`)
  .limit(1)

const t0 = Date.now()
const { remind } = await import("@/lib/services/task-commands")
const { currentUser } = await import("@/lib/services/session")
void currentUser
const [admin] = await db.select({ id: people.id, code: people.employeeCode }).from(people).where(eq(people.username, "narin"))
const res = await remind(
  { personId: admin!.id, employeeCode: admin!.code, name: "", positionTitle: null, department: null, level: "admin", tier: "admin", language: "en" },
  task!.id,
  "sonde de verification",
)
console.log("relance :", res)

await new Promise((r) => setTimeout(r, 1200))
const arrivee = cible.chunks.filter((c) => c.text.includes("notification"))
console.log("arrivé sur le flux du destinataire :", arrivee.length, "après", arrivee[0] ? `${arrivee[0].at - (t0 - Date.now() + arrivee[0].at)}` : "-", "ms depuis l'ouverture :", arrivee[0]?.at, "ms")
console.log("contenu :", arrivee[0]?.text.slice(0, 160))
console.log("reçu par le témoin (doit être 0) :", temoin.chunks.filter((c) => c.text.includes("notification")).length)

cible.close()
temoin.close()

// Remise en état.
await db.delete(notifications)
await db.delete(domainEvents)
await db.delete(taskSubmissions)
const [n] = await db.select({ n: sql<number>`count(*)::int` }).from(notifications)
const [e] = await db.select({ n: sql<number>`count(*)::int` }).from(domainEvents)
const [s] = await db.select({ n: sql<number>`count(*)::int` }).from(taskSubmissions)
const st = await db.select({ s: taskInstances.status, n: sql<number>`count(*)::int` }).from(taskInstances).groupBy(taskInstances.status).orderBy(taskInstances.status)
console.log("remis :", { notifications: n?.n, evenements: e?.n, rendus: s?.n })
console.log("statuts :", st)

void recurringTemplates
process.exit(0)
