import { NextRequest, NextResponse } from 'next/server'
import pool from '@/lib/db'
import { getSessionFromRequest } from '@/lib/session'

export interface OUNode {
  dn: string
  label: string
  path: string
  children: OUNode[]
  userCount: number
  groupCount: number
}

function dnToLabel(dn: string): string {
  const first = dn.split(',')[0] ?? dn
  return first.replace(/^(OU|CN|DC)=/i, '')
}

function buildTree(ous: { dn: string; userCount: number; groupCount: number }[]): OUNode[] {
  // Sort by depth (fewer commas = higher up)
  const sorted = [...ous].sort((a, b) => {
    const depthA = a.dn.split(',').length
    const depthB = b.dn.split(',').length
    return depthA - depthB
  })

  const nodeMap = new Map<string, OUNode>()
  const roots: OUNode[] = []

  for (const ou of sorted) {
    const node: OUNode = {
      dn: ou.dn,
      label: dnToLabel(ou.dn),
      path: ou.dn,
      children: [],
      userCount: ou.userCount,
      groupCount: ou.groupCount,
    }
    nodeMap.set(ou.dn, node)

    // Find parent: the dn without the first component
    const parts = ou.dn.split(',')
    const parentDn = parts.slice(1).join(',')
    const parent = nodeMap.get(parentDn)

    if (parent) {
      parent.children.push(node)
    } else {
      roots.push(node)
    }
  }

  return roots
}

export async function GET(req: NextRequest) {
  const user = await getSessionFromRequest(req)
  if (!user) return NextResponse.json({ error: 'Não autorizado' }, { status: 401 })

  const tenantId = user.role === 'admin_global'
    ? req.nextUrl.searchParams.get('tenant_id') ?? (user as any).tenant_id
    : (user as any).tenant_id ?? (user as any).tenantId

  if (!tenantId) return NextResponse.json({ error: 'Tenant não informado' }, { status: 400 })

  // ad_users usa `distinguished_name` (DN completo: CN=joao,OU=TI,DC=empresa,DC=local)
  // Extraímos a OU removendo o primeiro componente (CN=...)
  const [userOUs] = await pool.execute<any[]>(
    `SELECT SUBSTRING(distinguished_name, LOCATE(',', distinguished_name) + 1) AS dn,
            COUNT(*) as cnt
     FROM ad_users
     WHERE tenant_id = ? AND distinguished_name IS NOT NULL AND distinguished_name != ''
       AND LOCATE(',', distinguished_name) > 0
     GROUP BY dn`,
    [tenantId],
  )

  // ad_groups usa `dn` (DN completo: CN=grupo,OU=Grupos,DC=empresa,DC=local)
  const [groupOUs] = await pool.execute<any[]>(
    `SELECT SUBSTRING(dn, LOCATE(',', dn) + 1) AS dn,
            COUNT(*) as cnt
     FROM ad_groups
     WHERE tenant_id = ? AND dn IS NOT NULL AND dn != ''
       AND LOCATE(',', dn) > 0
     GROUP BY dn`,
    [tenantId],
  )

  // Also get tenant base_dn as root
  const [tenantRows] = await pool.execute<any[]>(
    'SELECT base_dn, name FROM tenants WHERE id = ?',
    [tenantId],
  )
  const baseDn: string = tenantRows[0]?.base_dn ?? ''
  const tenantName: string = tenantRows[0]?.name ?? 'Domínio'

  // Merge counts per OU
  const ouMap = new Map<string, { userCount: number; groupCount: number }>()

  // Add root
  if (baseDn) {
    ouMap.set(baseDn, { userCount: 0, groupCount: 0 })
  }

  for (const row of userOUs) {
    const existing = ouMap.get(row.dn) ?? { userCount: 0, groupCount: 0 }
    ouMap.set(row.dn, { ...existing, userCount: existing.userCount + Number(row.cnt) })
  }
  for (const row of groupOUs) {
    const existing = ouMap.get(row.dn) ?? { userCount: 0, groupCount: 0 }
    ouMap.set(row.dn, { ...existing, groupCount: existing.groupCount + Number(row.cnt) })
  }

  const ous = Array.from(ouMap.entries()).map(([dn, counts]) => ({ dn, ...counts }))
  const tree = buildTree(ous)

  return NextResponse.json({
    baseDn,
    tenantName,
    tree,
  })
}
