import { NextResponse } from "next/server"
import { ZodError } from "zod"
import { Prisma } from "@/lib/prisma"

import { prisma } from "@/lib/prisma"
import { assertStaffSession } from "@/lib/auth-server"
import { isAdmin } from "@/lib/authz"
import { removeConvexCompany, syncConvexCompany } from "@/server/companies-sync"
import {
  buildCompanyData,
  fetchCompanyById,
  formatZodError,
  normalizeCompany,
  sanitizeCompanyInput,
} from "@/server/company-service"
import type { CompanyFormValues } from "@/lib/schemas/company"

export const runtime = "nodejs"

function mergePayload(base: CompanyFormValues, updates: Record<string, unknown>): Record<string, unknown> {
  const merged: Record<string, unknown> = { ...base, ...updates }

  if (!("businessHours" in updates)) merged.businessHours = base.businessHours
  if (!("communicationChannels" in updates)) merged.communicationChannels = base.communicationChannels
  if (!("clientDomains" in updates)) merged.clientDomains = base.clientDomains
  if (!("fiscalAddress" in updates)) merged.fiscalAddress = base.fiscalAddress
  if (!("regulatedEnvironments" in updates)) merged.regulatedEnvironments = base.regulatedEnvironments
  if (!("contacts" in updates)) merged.contacts = base.contacts
  if (!("locations" in updates)) merged.locations = base.locations
  if (!("contracts" in updates)) merged.contracts = base.contracts
  if (!("sla" in updates)) merged.sla = base.sla
  if (!("tags" in updates)) merged.tags = base.tags
  if (!("customFields" in updates)) merged.customFields = base.customFields

  if ("privacyPolicy" in updates) {
    const incoming = updates.privacyPolicy
    if (incoming && typeof incoming === "object") {
      merged.privacyPolicy = {
        ...base.privacyPolicy,
        ...incoming,
      }
    }
  } else {
    merged.privacyPolicy = base.privacyPolicy
  }

  merged.tenantId = base.tenantId
  return merged
}

export async function PATCH(
  request: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const session = await assertStaffSession()
  if (!session) return NextResponse.json({ error: "Não autorizado" }, { status: 401 })
  if (!isAdmin(session.user.role)) {
    return NextResponse.json({ error: "Apenas administradores podem editar empresas" }, { status: 403 })
  }

  const { id } = await params

  try {
    const existing = await fetchCompanyById(id)
    if (!existing) {
      return NextResponse.json({ error: "Empresa não encontrada" }, { status: 404 })
    }

    if (existing.tenantId !== (session.user.tenantId ?? existing.tenantId)) {
      return NextResponse.json({ error: "Acesso negado" }, { status: 403 })
    }

    const rawBody = (await request.json()) as Record<string, unknown>
    const normalized = normalizeCompany(existing)
    const {
      id: _ignoreId,
      provisioningCode: _ignoreCode,
      createdAt: _createdAt,
      updatedAt: _updatedAt,
      ...baseForm
    } = normalized
    void _ignoreId
    void _ignoreCode
    void _createdAt
    void _updatedAt

    const mergedInput = mergePayload(baseForm, rawBody)
    const form = sanitizeCompanyInput(mergedInput, existing.tenantId)
    const createData = buildCompanyData(form, existing.tenantId)
    const { tenantId: _omitTenant, ...updateData } = createData
    void _omitTenant

    const company = await prisma.company.update({
      where: { id },
      data: updateData,
    })

    if (company.provisioningCode) {
      const synced = await syncConvexCompany({
        tenantId: company.tenantId,
        slug: company.slug,
        name: company.name,
        provisioningCode: company.provisioningCode,
      })
      if (!synced) {
        console.warn("[admin.companies] Convex não configurado; atualização aplicada apenas no Prisma.")
      }
    }

    return NextResponse.json({ company: normalizeCompany(company) })
  } catch (error) {
    if (error instanceof ZodError) {
      return NextResponse.json({ error: "Dados inválidos", issues: formatZodError(error) }, { status: 422 })
    }
    if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
      return NextResponse.json({ error: "Já existe uma empresa com este slug." }, { status: 409 })
    }
    console.error("Failed to update company", error)
    return NextResponse.json({ error: "Falha ao atualizar empresa" }, { status: 500 })
  }
}

export async function DELETE(
  _: Request,
  { params }: { params: Promise<{ id: string }> }
) {
  const session = await assertStaffSession()
  if (!session) return NextResponse.json({ error: "Não autorizado" }, { status: 401 })
  if (!isAdmin(session.user.role)) {
    return NextResponse.json({ error: "Apenas administradores podem excluir empresas" }, { status: 403 })
  }
  const { id } = await params

  const company = await fetchCompanyById(id)

  if (!company) {
    return NextResponse.json({ error: "Empresa não encontrada" }, { status: 404 })
  }

  if (company.tenantId !== (session.user.tenantId ?? company.tenantId)) {
    return NextResponse.json({ error: "Acesso negado" }, { status: 403 })
  }

  try {
    const result = await prisma.$transaction(async (tx: Prisma.TransactionClient) => {
      const users = await tx.user.updateMany({
        where: { companyId: company.id, tenantId: company.tenantId },
        data: { companyId: null },
      })
      const tickets = await tx.ticket.updateMany({
        where: { companyId: company.id, tenantId: company.tenantId },
        data: { companyId: null },
      })
      await tx.company.delete({ where: { id: company.id } })
      return { detachedUsers: users.count, detachedTickets: tickets.count }
    })

    if (company.slug) {
      const removed = await removeConvexCompany({
        tenantId: company.tenantId,
        slug: company.slug,
      })
      if (!removed) {
        console.warn("[admin.companies] Convex não configurado; empresa removida apenas no Prisma.")
      }
    }

    return NextResponse.json({ ok: true, ...result })
  } catch (error) {
    if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2003") {
      return NextResponse.json(
        { error: "Não é possível remover esta empresa pois existem registros vinculados." },
        { status: 409 }
      )
    }
    console.error("Failed to delete company", error)
    return NextResponse.json({ error: "Falha ao excluir empresa" }, { status: 500 })
  }
}
