import { NextResponse } from "next/server"
import { ConvexHttpClient } from "convex/browser"

import { api } from "@/convex/_generated/api"
import type { Id } from "@/convex/_generated/dataModel"
import { assertAdminSession } from "@/lib/auth-server"
import { env } from "@/lib/env"
import { prisma } from "@/lib/prisma"
import { sendSmtpMail } from "@/server/email-smtp"

export const runtime = "nodejs"

function fmtHours(ms: number) {
  return (ms / 3600000).toFixed(2)
}

export async function POST(request: Request) {
  const session = await assertAdminSession()
  if (!session) return NextResponse.json({ error: "Não autorizado" }, { status: 401 })

  const convexUrl = process.env.NEXT_PUBLIC_CONVEX_URL
  if (!convexUrl) return NextResponse.json({ error: "Convex não configurado" }, { status: 500 })
  if (!env.SMTP) return NextResponse.json({ error: "SMTP não configurado" }, { status: 500 })

  const { searchParams } = new URL(request.url)
  const range = searchParams.get("range") ?? "30d"
  const threshold = Number(searchParams.get("threshold") ?? 90)

  const client = new ConvexHttpClient(convexUrl)
  const tenantId = session.user.tenantId ?? "tenant-atlas"

  // Ensure user exists in Convex to obtain a typed viewerId
  let viewerId: Id<"users"> | null = null
  try {
    const ensured = await client.mutation(api.users.ensureUser, {
      tenantId,
      name: session.user.name ?? session.user.email,
      email: session.user.email,
      avatarUrl: session.user.avatarUrl ?? undefined,
      role: session.user.role.toUpperCase(),
    })
    viewerId = (ensured?._id ?? null) as Id<"users"> | null
  } catch (error) {
    console.error("Failed to synchronize user with Convex for alerts", error)
    return NextResponse.json({ error: "Falha ao sincronizar usuário com Convex" }, { status: 500 })
  }
  if (!viewerId) return NextResponse.json({ error: "Usuário não encontrado no Convex" }, { status: 403 })

  const report = await client.query(api.reports.hoursByClient, {
    tenantId,
    viewerId,
    range,
  })

  type HoursByClientItem = {
    companyId: Id<"companies">
    name: string
    internalMs: number
    externalMs: number
    totalMs: number
    contractedHoursPerMonth: number | null
  }
  const items = (report.items ?? []) as HoursByClientItem[]
  const alerts = items.filter((i) => i.contractedHoursPerMonth != null && (i.totalMs / 3600000) / (i.contractedHoursPerMonth || 1) * 100 >= threshold)

  for (const item of alerts) {
    // Find managers of the company in Prisma
    const managers = await prisma.user.findMany({
      where: {
        tenantId,
        companyId: item.companyId,
        role: "MANAGER",
      },
      select: { email: true, name: true },
    })
    if (managers.length === 0) continue

    const subject = `Alerta: uso de horas em ${item.name} acima de ${threshold}%`
    const body = `
      <p>Olá,</p>
      <p>O uso de horas contratadas para <strong>${item.name}</strong> atingiu <strong>${(((item.totalMs/3600000)/(item.contractedHoursPerMonth || 1))*100).toFixed(1)}%</strong>.</p>
      <ul>
        <li>Horas internas: <strong>${fmtHours(item.internalMs)}</strong></li>
        <li>Horas externas: <strong>${fmtHours(item.externalMs)}</strong></li>
        <li>Total: <strong>${fmtHours(item.totalMs)}</strong></li>
        <li>Contratadas/mês: <strong>${item.contractedHoursPerMonth}</strong></li>
      </ul>
      <p>Reveja a alocação da equipe e, se necessário, ajuste o atendimento.</p>
    `
    let delivered = 0
    for (const m of managers) {
      try {
        await sendSmtpMail(
          {
            host: env.SMTP!.host,
            port: env.SMTP!.port,
            username: env.SMTP!.username,
            password: env.SMTP!.password,
            from: env.SMTP!.from!,
          },
          m.email,
          subject,
          body
        )
        delivered += 1
      } catch (error) {
        console.error("Failed to send alert to", m.email, error)
      }
    }
    try {
      await client.mutation(api.alerts.log, {
        tenantId,
        companyId: item.companyId,
        companyName: item.name,
        usagePct: (((item.totalMs/3600000)/(item.contractedHoursPerMonth || 1))*100),
        threshold,
        range,
        recipients: managers.map((m) => m.email),
        deliveredCount: delivered,
      })
    } catch (error) {
      console.error("Failed to log alert in Convex", error)
    }
  }

  return NextResponse.json({ sent: alerts.length })
}
