import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/db'
import { getSession } from '@/lib/auth'

async function getTenantId() {
  const user = await getSession()
  if (!user) return { error: 'Nicht autorisiert', status: 401 }
  if (user.role !== 'TENANT_ADMIN' && user.role !== 'SERVER_ADMIN') {
    return { error: 'Keine Berechtigung', status: 403 }
  }
  if (!user.tenantId) return { error: 'Kein Mandant zugeordnet', status: 400 }
  return { tenantId: user.tenantId }
}

async function ensureTable() {
  await prisma.$executeRawUnsafe(`
    CREATE TABLE IF NOT EXISTS tenant_categories (
      id TEXT PRIMARY KEY DEFAULT gen_random_uuid(),
      "name" TEXT NOT NULL,
      "description" TEXT,
      "sortOrder" INTEGER NOT NULL DEFAULT 0,
      "isActive" BOOLEAN NOT NULL DEFAULT true,
      "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
      "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
      "tenantId" TEXT NOT NULL REFERENCES tenants(id) ON DELETE CASCADE
    )
  `)
}

// ─── GET ────────────────────────────────────────────────────────────────────

export async function GET() {
  try {
    const auth = await getTenantId()
    if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })
    const { tenantId } = auth

    await ensureTable()

    const categories: any[] = await prisma.$queryRawUnsafe(
      `SELECT * FROM tenant_categories WHERE "tenantId" = $1 AND "isActive" = true ORDER BY "sortOrder" ASC`,
      tenantId
    )

    return NextResponse.json({ categories })
  } catch (error) {
    console.error('Error fetching tenant categories:', error)
    return NextResponse.json({ error: 'Interner Fehler' }, { status: 500 })
  }
}

// ─── POST ───────────────────────────────────────────────────────────────────

export async function POST(req: NextRequest) {
  try {
    const auth = await getTenantId()
    if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })
    const { tenantId } = auth

    const { name, sortOrder } = await req.json()
    if (!name || typeof name !== 'string') {
      return NextResponse.json({ error: 'Name erforderlich' }, { status: 400 })
    }

    await ensureTable()

    // Check for duplicate
    const existing = await prisma.$queryRawUnsafe(
      `SELECT id FROM tenant_categories WHERE "tenantId" = $1 AND LOWER(name) = LOWER($2) LIMIT 1`,
      tenantId, name.trim()
    ) as any[]
    if (existing && existing.length > 0) {
      return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 })
    }

    const result = await prisma.$queryRawUnsafe(
      `INSERT INTO tenant_categories (id, "tenantId", name, "sortOrder", "createdAt", "updatedAt")
       VALUES (gen_random_uuid(), $1, $2, $3, NOW(), NOW())
       RETURNING *`,
      tenantId, name.trim(), sortOrder ?? 0
    ) as any[]

    return NextResponse.json({ category: result[0] }, { status: 201 })
  } catch (error) {
    console.error('Error creating tenant category:', error)
    return NextResponse.json({ error: 'Interner Fehler' }, { status: 500 })
  }
}

// ─── PATCH ──────────────────────────────────────────────────────────────────

export async function PATCH(req: NextRequest) {
  try {
    const auth = await getTenantId()
    if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })
    const { tenantId } = auth

    const { id, name, sortOrder } = await req.json()
    if (!id) return NextResponse.json({ error: 'id erforderlich' }, { status: 400 })

    await ensureTable()

    // If renaming, check for duplicates
    if (name) {
      const existing = await prisma.$queryRawUnsafe(
        `SELECT id FROM tenant_categories WHERE "tenantId" = $1 AND LOWER(name) = LOWER($2) AND id != $3 LIMIT 1`,
        tenantId, name.trim(), id
      ) as any[]
      if (existing && existing.length > 0) {
        return NextResponse.json({ error: 'Kategorie existiert bereits' }, { status: 409 })
      }
    }

    const updates: string[] = []
    const params: any[] = [id, tenantId]
    if (name !== undefined) { updates.push(`name = $${params.length + 1}`); params.push(name.trim()); }
    if (sortOrder !== undefined) { updates.push(`"sortOrder" = $${params.length + 1}`); params.push(sortOrder); }
    updates.push(`"updatedAt" = NOW()`)

    const result = await prisma.$queryRawUnsafe(
      `UPDATE tenant_categories SET ${updates.join(', ')} WHERE id = $1 AND "tenantId" = $2 RETURNING *`,
      ...params
    ) as any[]

    if (!result || result.length === 0) {
      return NextResponse.json({ error: 'Kategorie nicht gefunden' }, { status: 404 })
    }

    return NextResponse.json({ success: true })
  } catch (error) {
    console.error('Error updating tenant category:', error)
    return NextResponse.json({ error: 'Interner Fehler' }, { status: 500 })
  }
}

// ─── DELETE ─────────────────────────────────────────────────────────────────

export async function DELETE(req: NextRequest) {
  try {
    const auth = await getTenantId()
    if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })
    const { tenantId } = auth

    const { id } = await req.json()
    if (!id) return NextResponse.json({ error: 'id erforderlich' }, { status: 400 })

    await ensureTable()

    // Check if category has symbols
    const symbolCount = await prisma.$queryRawUnsafe(
      `SELECT COUNT(*)::int as cnt FROM tenant_symbols WHERE "categoryId" = $1 AND "tenantId" = $2`,
      id, tenantId
    ) as any[]
    if (symbolCount && symbolCount[0]?.cnt > 0) {
      return NextResponse.json(
        { error: `Kategorie enthält ${symbolCount[0].cnt} Symbol(e) — bitte zuerst verschieben oder löschen` },
        { status: 409 }
      )
    }

    await prisma.$queryRawUnsafe(
      `DELETE FROM tenant_categories WHERE id = $1 AND "tenantId" = $2`,
      id, tenantId
    )

    return NextResponse.json({ success: true })
  } catch (error) {
    console.error('Error deleting tenant category:', error)
    return NextResponse.json({ error: 'Interner Fehler' }, { status: 500 })
  }
}
