import { type NextRequest, NextResponse } from "next/server"
import { safeQuery } from "@/lib/database"

type ManagedTypeKind = "field" | "department" | "team"

const managedTypeKinds: ManagedTypeKind[] = ["field", "department", "team"]

type AdminScope = {
  role: string
  field?: string | null
  department?: string | null
  team?: string | null
}

const getAdminScope = async (adminId?: string) => {
  if (!adminId) {
    return { ok: false, response: NextResponse.json({ error: "Missing admin id." }, { status: 400 }) }
  }

  const adminRows = (await safeQuery("SELECT role, field, department, team FROM users WHERE national_id = ?", [
    adminId,
  ])) as AdminScope[]

  if (adminRows.length === 0) {
    return { ok: false, response: NextResponse.json({ error: "Admin not found." }, { status: 404 }) }
  }

  return { ok: true as const, admin: adminRows[0] }
}

export async function GET(request: NextRequest) {
  try {
    const adminId = request.nextUrl.searchParams.get("adminId") || undefined
    const adminCheck = await getAdminScope(adminId)
    if (!adminCheck.ok) {
      return adminCheck.response
    }

    const admin = adminCheck.admin

    const managedRows = (await safeQuery(
      "SELECT id, type, name, parent_id AS parentId FROM managed_types ORDER BY type, name",
    )) as Array<{ id: number; type: ManagedTypeKind; name: string; parentId: number | null }>

    const [fieldsFromUsers, departmentsFromUsers, teamsFromUsers] = await Promise.all([
      safeQuery("SELECT DISTINCT field AS name FROM users WHERE field IS NOT NULL AND field <> '' ORDER BY field"),
      safeQuery(
        "SELECT DISTINCT department AS name FROM users WHERE department IS NOT NULL AND department <> '' ORDER BY department",
      ),
      safeQuery("SELECT DISTINCT team AS name FROM users WHERE team IS NOT NULL AND team <> '' ORDER BY team"),
    ])

    const byType = {
      field: managedRows.filter((row) => row.type === "field"),
      department: managedRows.filter((row) => row.type === "department"),
      team: managedRows.filter((row) => row.type === "team"),
    }

    const merge = (
      managed: Array<{ id: number; name: string; parentId: number | null }>,
      fromUsers: Array<{ name: string }>,
    ) => {
      const map = new Map<
        string,
        { id?: number; name: string; managed: boolean; parentId?: number | null }
      >()

      managed.forEach((row) => {
        map.set(row.name, { id: row.id, name: row.name, managed: true, parentId: row.parentId })
      })

      fromUsers.forEach((row) => {
        if (!map.has(row.name)) {
          map.set(row.name, { name: row.name, managed: false, parentId: null })
        }
      })

      return Array.from(map.values()).sort((a, b) => a.name.localeCompare(b.name))
    }

    let fields = merge(byType.field, fieldsFromUsers as any[])
    let departments = merge(byType.department, departmentsFromUsers as any[])
    let teams = merge(byType.team, teamsFromUsers as any[])

    if (admin.role === "field_admin") {
      fields = fields.filter((field) => field.name === admin.field)
      const fieldId = fields[0]?.id
      departments = fieldId ? departments.filter((dept) => dept.parentId === fieldId) : []
      const departmentIds = new Set(departments.map((dept) => dept.id))
      teams = teams.filter((team) => team.parentId && departmentIds.has(team.parentId))
    } else if (admin.role === "department_admin") {
      fields = fields.filter((field) => field.name === admin.field)
      departments = departments.filter((dept) => dept.name === admin.department)
      const departmentId = departments[0]?.id
      teams = departmentId ? teams.filter((team) => team.parentId === departmentId) : []
    } else if (admin.role === "team_admin") {
      fields = fields.filter((field) => field.name === admin.field)
      departments = departments.filter((dept) => dept.name === admin.department)
      teams = teams.filter((team) => team.name === admin.team)
    }

    return NextResponse.json({ fields, departments, teams })
  } catch (error) {
    console.error("Managed types fetch error:", error)
    return NextResponse.json({ error: "Failed to load managed types." }, { status: 500 })
  }
}

export async function POST(request: NextRequest) {
  try {
    const { adminId, type, name, parentId } = await request.json()

    const adminCheck = await getAdminScope(adminId)
    if (!adminCheck.ok) {
      return adminCheck.response
    }

    const admin = adminCheck.admin

    if (!managedTypeKinds.includes(type)) {
      return NextResponse.json({ error: "Invalid type." }, { status: 400 })
    }

    const trimmedName = typeof name === "string" ? name.trim() : ""
    if (!trimmedName) {
      return NextResponse.json({ error: "Name is required." }, { status: 400 })
    }

    if (type === "field") {
      if (admin.role !== "global_admin" && admin.role !== "field_admin") {
        return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
      }
      if (admin.role === "field_admin" && admin.field && admin.field !== trimmedName) {
        return NextResponse.json({ error: "Field admins can only manage their field." }, { status: 403 })
      }
      await safeQuery("INSERT INTO managed_types (type, name, parent_id) VALUES (?, ?, NULL)", [type, trimmedName])
    } else if (type === "department") {
      if (!parentId) {
        return NextResponse.json({ error: "Parent field is required." }, { status: 400 })
      }
      if (admin.role === "department_admin" || admin.role === "team_admin") {
        return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
      }
      if (admin.role === "field_admin") {
        const fieldRows = (await safeQuery("SELECT id, name FROM managed_types WHERE id = ? AND type = 'field'", [
          parentId,
        ])) as Array<{ id: number; name: string }>
        if (fieldRows.length === 0 || fieldRows[0].name !== admin.field) {
          return NextResponse.json({ error: "Field admins can only manage their field." }, { status: 403 })
        }
      }
      await safeQuery("INSERT INTO managed_types (type, name, parent_id) VALUES (?, ?, ?)", [
        type,
        trimmedName,
        parentId,
      ])
    } else {
      if (!parentId) {
        return NextResponse.json({ error: "Parent department is required." }, { status: 400 })
      }
      if (admin.role === "team_admin") {
        return NextResponse.json({ error: "Insufficient permissions." }, { status: 403 })
      }
      if (admin.role === "department_admin") {
        const departmentRows = (await safeQuery(
          "SELECT id, name FROM managed_types WHERE id = ? AND type = 'department'",
          [parentId],
        )) as Array<{ id: number; name: string }>
        if (departmentRows.length === 0 || departmentRows[0].name !== admin.department) {
          return NextResponse.json({ error: "Department admins can only manage their department." }, { status: 403 })
        }
      }
      if (admin.role === "field_admin") {
        const departmentRows = (await safeQuery(
          "SELECT id, parent_id AS parentId FROM managed_types WHERE id = ? AND type = 'department'",
          [parentId],
        )) as Array<{ id: number; parentId: number | null }>
        if (departmentRows.length === 0) {
          return NextResponse.json({ error: "Department not found." }, { status: 404 })
        }
        const fieldRows = (await safeQuery("SELECT id, name FROM managed_types WHERE id = ?", [
          departmentRows[0].parentId,
        ])) as Array<{ id: number; name: string }>
        if (fieldRows.length === 0 || fieldRows[0].name !== admin.field) {
          return NextResponse.json({ error: "Field admins can only manage their field." }, { status: 403 })
        }
      }
      await safeQuery("INSERT INTO managed_types (type, name, parent_id) VALUES (?, ?, ?)", [
        type,
        trimmedName,
        parentId,
      ])
    }

    return NextResponse.json({ success: true })
  } catch (error: any) {
    if (error?.code === "ER_DUP_ENTRY") {
      return NextResponse.json({ error: "Value already exists." }, { status: 409 })
    }
    console.error("Managed types create error:", error)
    return NextResponse.json({ error: "Failed to create managed type." }, { status: 500 })
  }
}
