import { ConvexError, v } from "convex/values"

import { mutation, query } from "./_generated/server"
import type { Id } from "./_generated/dataModel"
import { requireStaff } from "./rbac"

const DEFAULT_STATUS = "investigating"

function timelineId() {
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
    return crypto.randomUUID()
  }
  return `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`
}

export const list = query({
  args: { tenantId: v.string(), viewerId: v.id("users") },
  handler: async (ctx, { tenantId, viewerId }) => {
    await requireStaff(ctx, viewerId, tenantId)
    const incidents = await ctx.db
      .query("incidents")
      .withIndex("by_tenant_updated", (q) => q.eq("tenantId", tenantId))
      .order("desc")
      .take(100)
    return incidents
  },
})

export const createIncident = mutation({
  args: {
    tenantId: v.string(),
    actorId: v.id("users"),
    title: v.string(),
    severity: v.string(),
    impactSummary: v.optional(v.string()),
    affectedQueues: v.optional(v.array(v.string())),
    initialUpdate: v.optional(v.string()),
  },
  handler: async (ctx, { tenantId, actorId, title, severity, impactSummary, affectedQueues, initialUpdate }) => {
    const viewer = await requireStaff(ctx, actorId, tenantId)
    const normalizedTitle = title.trim()
    if (normalizedTitle.length < 3) {
      throw new ConvexError("Informe um título válido para o incidente")
    }
    const now = Date.now()
    const timelineEntry = {
      id: timelineId(),
      authorId: actorId,
      authorName: viewer.user.name ?? viewer.user.email ?? "Equipe",
      message: initialUpdate?.trim().length ? initialUpdate.trim() : "Incidente registrado.",
      type: "created",
      createdAt: now,
    }
    const id = await ctx.db.insert("incidents", {
      tenantId,
      title: normalizedTitle,
      status: DEFAULT_STATUS,
      severity,
      impactSummary: impactSummary?.trim() || undefined,
      affectedQueues: affectedQueues ?? [],
      ownerId: actorId,
      ownerName: viewer.user.name ?? undefined,
      ownerEmail: viewer.user.email ?? undefined,
      startedAt: now,
      updatedAt: now,
      resolvedAt: undefined,
      timeline: [timelineEntry],
    })
    return id
  },
})

export const updateIncidentStatus = mutation({
  args: {
    tenantId: v.string(),
    actorId: v.id("users"),
    incidentId: v.id("incidents"),
    status: v.string(),
  },
  handler: async (ctx, { tenantId, actorId, incidentId, status }) => {
    const viewer = await requireStaff(ctx, actorId, tenantId)
    const incident = await ctx.db.get(incidentId)
    if (!incident || incident.tenantId !== tenantId) {
      throw new ConvexError("Incidente não encontrado")
    }
    const now = Date.now()
    const timeline = [
      ...(incident.timeline ?? []),
      {
        id: timelineId(),
        authorId: actorId,
        authorName: viewer.user.name ?? viewer.user.email ?? "Equipe",
        message: `Status atualizado para ${status}`,
        type: "status",
        createdAt: now,
      },
    ]
    await ctx.db.patch(incidentId, {
      status,
      updatedAt: now,
      resolvedAt: status === "resolved" ? now : incident.resolvedAt ?? undefined,
      timeline,
    })
  },
})

export const bulkUpdateIncidentStatus = mutation({
  args: {
    tenantId: v.string(),
    actorId: v.id("users"),
    incidentIds: v.array(v.id("incidents")),
    status: v.string(),
  },
  handler: async (ctx, { tenantId, actorId, incidentIds, status }) => {
    const viewer = await requireStaff(ctx, actorId, tenantId)
    const now = Date.now()
    for (const incidentId of incidentIds) {
      const incident = await ctx.db.get(incidentId)
      if (!incident || incident.tenantId !== tenantId) continue
      const timeline = [
        ...(incident.timeline ?? []),
        {
          id: timelineId(),
          authorId: actorId,
          authorName: viewer.user.name ?? viewer.user.email ?? "Equipe",
          message: `Status atualizado em massa para ${status}`,
          type: "status",
          createdAt: now,
        },
      ]
      await ctx.db.patch(incidentId, {
        status,
        updatedAt: now,
        resolvedAt: status === "resolved" ? now : incident.resolvedAt ?? undefined,
        timeline,
      })
    }
  },
})

export const addIncidentUpdate = mutation({
  args: {
    tenantId: v.string(),
    actorId: v.id("users"),
    incidentId: v.id("incidents"),
    message: v.string(),
    status: v.optional(v.string()),
  },
  handler: async (ctx, { tenantId, actorId, incidentId, message, status }) => {
    const viewer = await requireStaff(ctx, actorId, tenantId)
    const incident = await ctx.db.get(incidentId)
    if (!incident || incident.tenantId !== tenantId) {
      throw new ConvexError("Incidente não encontrado")
    }
    const trimmed = message.trim()
    if (trimmed.length < 3) {
      throw new ConvexError("Descreva a atualização do incidente")
    }
    const now = Date.now()
    const timeline = [
      ...(incident.timeline ?? []),
      {
        id: timelineId(),
        authorId: actorId,
        authorName: viewer.user.name ?? viewer.user.email ?? "Equipe",
        message: trimmed,
        type: "update",
        createdAt: now,
      },
    ]
    await ctx.db.patch(incidentId, {
      timeline,
      status: status ?? incident.status,
      updatedAt: now,
      resolvedAt: status === "resolved" ? now : incident.resolvedAt ?? undefined,
    })
  },
})
