import { prisma } from '@/lib/db'
import { apiRoute } from '@/lib/api/handler'

export const dynamic = 'force-dynamic'

/**
 * Global search (§60).
 *
 * One endpoint over seven entity kinds, because the operator's question is "where is
 * T-108" rather than "which table is T-108 in". Each kind is gated on the permission
 * that governs its own page, so search can never become a way to see something the
 * console would not show you — a search box that quietly returns forbidden records is a
 * classic and expensive hole.
 *
 * The query is passed to Prisma as a value, never interpolated, so the usual injection
 * shapes are inert.
 */
export interface SearchHit {
  kind: 'asset' | 'region' | 'incident' | 'pattern' | 'alert' | 'simulation' | 'maintenance'
  code: string
  label: string
  labelAr: string
  detail: string
  href: string
}

const MAX_PER_KIND = 5

export const GET = apiRoute({ limit: 120 }, async ({ searchParams, user }) => {
  const query = (searchParams.get('q') ?? '').trim()
  if (query.length < 2) return { query, hits: [] as SearchHit[] }

  const like = { contains: query } as const
  const can = (permission: string) => user.permissions.has(permission)
  const hits: SearchHit[] = []

  if (can('assets.read')) {
    const assets = await prisma.asset.findMany({
      where: { OR: [{ code: like }, { name: like }, { nameAr: like }] },
      take: MAX_PER_KIND,
      select: {
        code: true,
        name: true,
        nameAr: true,
        capacityMw: true,
        assetType: { select: { key: true } },
        region: { select: { code: true } },
      },
    })
    hits.push(
      ...assets.map((asset) => ({
        kind: 'asset' as const,
        code: asset.code,
        label: asset.name,
        labelAr: asset.nameAr,
        detail: `${asset.assetType.key} · ${asset.region.code} · ${Math.round(asset.capacityMw)} MW`,
        href: `/assets/${encodeURIComponent(asset.code)}`,
      })),
    )
  }

  if (can('grid.read')) {
    const regions = await prisma.region.findMany({
      where: { OR: [{ code: like }, { name: like }, { nameAr: like }] },
      take: MAX_PER_KIND,
      select: { code: true, name: true, nameAr: true, peakDemandMw: true },
    })
    hits.push(
      ...regions.map((region) => ({
        kind: 'region' as const,
        code: region.code,
        label: region.name,
        labelAr: region.nameAr,
        detail: `${Math.round(region.peakDemandMw)} MW peak demand`,
        href: `/map?region=${encodeURIComponent(region.code)}`,
      })),
    )
  }

  if (can('incidents.read')) {
    const incidents = await prisma.incident.findMany({
      where: { OR: [{ code: like }, { title: like }, { titleAr: like }] },
      take: MAX_PER_KIND,
      orderBy: { startedAt: 'desc' },
      select: { code: true, title: true, titleAr: true, severity: true },
    })
    hits.push(
      ...incidents.map((incident) => ({
        kind: 'incident' as const,
        code: incident.code,
        label: incident.title,
        labelAr: incident.titleAr,
        detail: incident.severity,
        href: `/incidents/${encodeURIComponent(incident.code)}`,
      })),
    )
  }

  if (can('dna.read')) {
    const patterns = await prisma.failurePattern.findMany({
      where: { OR: [{ code: like }, { name: like }, { nameAr: like }] },
      take: MAX_PER_KIND,
      select: { code: true, name: true, nameAr: true, eventType: true },
    })
    hits.push(
      ...patterns.map((pattern) => ({
        kind: 'pattern' as const,
        code: pattern.code,
        label: pattern.name,
        labelAr: pattern.nameAr,
        detail: pattern.eventType,
        href: `/failure-dna?focus=${encodeURIComponent(pattern.code)}`,
      })),
    )
  }

  if (can('alerts.read')) {
    const alerts = await prisma.alert.findMany({
      where: { OR: [{ code: like }, { title: like }, { titleAr: like }] },
      take: MAX_PER_KIND,
      orderBy: { createdAt: 'desc' },
      select: { code: true, title: true, titleAr: true, level: true, status: true },
    })
    hits.push(
      ...alerts.map((alert) => ({
        kind: 'alert' as const,
        code: alert.code,
        label: alert.title,
        labelAr: alert.titleAr,
        detail: `${alert.level} · ${alert.status}`,
        href: `/alerts?focus=${encodeURIComponent(alert.code)}`,
      })),
    )
  }

  if (can('simulations.read')) {
    const simulations = await prisma.twinSimulation.findMany({
      where: { code: like },
      take: MAX_PER_KIND,
      orderBy: { createdAt: 'desc' },
      select: { code: true, summary: true, summaryAr: true, riskAfter: true },
    })
    hits.push(
      ...simulations.map((simulation) => ({
        kind: 'simulation' as const,
        code: simulation.code,
        label: simulation.summary.slice(0, 70),
        labelAr: simulation.summaryAr.slice(0, 70),
        detail: `risk ${Math.round(simulation.riskAfter)} %`,
        href: `/digital-twin?simulation=${encodeURIComponent(simulation.code)}`,
      })),
    )
  }

  if (can('maintenance.read')) {
    const records = await prisma.maintenanceRecord.findMany({
      where: { OR: [{ code: like }, { findings: like }] },
      take: MAX_PER_KIND,
      orderBy: { scheduledAt: 'desc' },
      select: { code: true, kind: true, status: true, findings: true, findingsAr: true },
    })
    hits.push(
      ...records.map((record) => ({
        kind: 'maintenance' as const,
        code: record.code,
        label: record.findings.slice(0, 70) || record.kind,
        labelAr: record.findingsAr.slice(0, 70) || record.kind,
        detail: `${record.kind} · ${record.status}`,
        href: `/maintenance?focus=${encodeURIComponent(record.code)}`,
      })),
    )
  }

  return { query, hits }
})
