import { ConvexError, v } from "convex/values";
import { mutation, query } from "./_generated/server";
import { requireStaff } from "./rbac";

function normalizeSlug(input?: string | null): string | undefined {
  if (!input) return undefined
  const trimmed = input.trim()
  if (!trimmed) return undefined
  const ascii = trimmed
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .replace(/[\u2013\u2014]/g, "-")
  const sanitized = ascii.replace(/[^\w\s-]/g, "").replace(/[_\s]+/g, "-")
  const collapsed = sanitized.replace(/-+/g, "-").toLowerCase()
  const normalized = collapsed.replace(/^-+|-+$/g, "")
  return normalized || undefined
}

export const list = query({
  args: { tenantId: v.string(), viewerId: v.id("users") },
  handler: async (ctx, { tenantId, viewerId }) => {
    await requireStaff(ctx, viewerId, tenantId)
    const companies = await ctx.db
      .query("companies")
      .withIndex("by_tenant", (q) => q.eq("tenantId", tenantId))
      .take(200)
    return companies.map((c) => ({ id: c._id, name: c.name, slug: c.slug }))
  },
})

export const ensureProvisioned = mutation({
  args: {
    tenantId: v.string(),
    slug: v.string(),
    name: v.string(),
    provisioningCode: v.string(),
  },
  handler: async (ctx, { tenantId, slug, name, provisioningCode }) => {
    const normalizedSlug = normalizeSlug(slug)
    if (!normalizedSlug) {
      throw new ConvexError("Slug inválido")
    }
    const trimmedName = name.trim()
    if (!trimmedName) {
      throw new ConvexError("Nome inválido")
    }

    const existing = await ctx.db
      .query("companies")
      .withIndex("by_tenant_slug", (q) => q.eq("tenantId", tenantId).eq("slug", normalizedSlug))
      .unique()

    if (existing) {
      if (existing.provisioningCode !== provisioningCode) {
        await ctx.db.patch(existing._id, { provisioningCode })
      }
      return {
        id: existing._id,
        slug: existing.slug,
        name: existing.name,
      }
    }

    const now = Date.now()
    const id = await ctx.db.insert("companies", {
      tenantId,
      name: trimmedName,
      slug: normalizedSlug,
      provisioningCode,
      isAvulso: false,
      contractedHoursPerMonth: undefined,
      cnpj: undefined,
      domain: undefined,
      phone: undefined,
      description: undefined,
      address: undefined,
      legalName: undefined,
      tradeName: undefined,
      stateRegistration: undefined,
      stateRegistrationType: undefined,
      primaryCnae: undefined,
      timezone: undefined,
      businessHours: undefined,
      supportEmail: undefined,
      billingEmail: undefined,
      contactPreferences: undefined,
      clientDomains: undefined,
      communicationChannels: undefined,
      fiscalAddress: undefined,
      hasBranches: false,
      regulatedEnvironments: undefined,
      privacyPolicyAccepted: false,
      privacyPolicyReference: undefined,
      privacyPolicyMetadata: undefined,
      contracts: undefined,
      contacts: undefined,
      locations: undefined,
      sla: undefined,
      tags: undefined,
      customFields: undefined,
      notes: undefined,
      createdAt: now,
      updatedAt: now,
    })

    return {
      id,
      slug: normalizedSlug,
      name: trimmedName,
    }
  },
})

export const removeBySlug = mutation({
  args: {
    tenantId: v.string(),
    slug: v.string(),
  },
  handler: async (ctx, { tenantId, slug }) => {
    const normalizedSlug = normalizeSlug(slug) ?? slug
    const existing = await ctx.db
      .query("companies")
      .withIndex("by_tenant_slug", (q) => q.eq("tenantId", tenantId).eq("slug", normalizedSlug))
      .unique()

    if (!existing) {
      return { removed: false }
    }

    // Preserve company snapshot on related tickets before deletion
    const relatedTickets = await ctx.db
      .query("tickets")
      .withIndex("by_tenant_company", (q) => q.eq("tenantId", tenantId).eq("companyId", existing._id))
      .take(200)
    if (relatedTickets.length > 0) {
      const companySnapshot = {
        name: existing.name,
        slug: existing.slug,
        isAvulso: existing.isAvulso ?? undefined,
      }
      for (const t of relatedTickets) {
        const needsPatch = !t.companySnapshot ||
          t.companySnapshot.name !== companySnapshot.name ||
          t.companySnapshot.slug !== companySnapshot.slug ||
          Boolean(t.companySnapshot.isAvulso ?? false) !== Boolean(companySnapshot.isAvulso ?? false)
        if (needsPatch) {
          await ctx.db.patch(t._id, { companySnapshot })
        }
      }
    }

    await ctx.db.delete(existing._id)
    return { removed: true }
  },
})
