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

export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params
    const user = await getSession()
    if (!user) {
      return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 401 })
    }

    const project = await getProjectWithTenantCheck(id, user)
    if (!project) {
      return NextResponse.json({ error: 'Projekt nicht gefunden' }, { status: 404 })
    }

    const [features, proj] = await Promise.all([
      (prisma as any).feature.findMany({
        where: { projectId: id },
        orderBy: { createdAt: 'asc' },
      }),
      (prisma as any).project.findUnique({ where: { id }, select: { featuresVersion: true } }),
    ])

    return NextResponse.json({ features, featuresVersion: proj?.featuresVersion ?? 0 })
  } catch (error) {
    console.error('Error fetching features:', error)
    return NextResponse.json({ error: 'Serverfehler' }, { status: 500 })
  }
}

export async function POST(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params
    const user = await getSession()
    if (!user) {
      return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 401 })
    }

    if (user.role === 'VIEWER') {
      return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 })
    }

    const project = await getProjectWithTenantCheck(id, user)
    if (!project) {
      return NextResponse.json({ error: 'Projekt nicht gefunden' }, { status: 404 })
    }

    if (project.isLocked && user.role !== 'SERVER_ADMIN') {
      return NextResponse.json({ error: 'Projekt ist gesperrt' }, { status: 403 })
    }

    const body = await request.json()
    const validated = featureSchema.safeParse(body)
    
    if (!validated.success) {
      return NextResponse.json(
        { error: 'Ungültige Eingabedaten', details: validated.error.flatten() },
        { status: 400 }
      )
    }

    const feature = await (prisma as any).feature.create({
      data: {
        projectId: id,
        type: validated.data.type,
        geometry: validated.data.geometry,
        properties: validated.data.properties || {},
      },
    })

    return NextResponse.json({ feature }, { status: 201 })
  } catch (error) {
    console.error('Error creating feature:', error)
    return NextResponse.json({ error: 'Serverfehler' }, { status: 500 })
  }
}

export async function PUT(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { id } = await params
    const user = await getSession()
    if (!user) {
      return NextResponse.json({ error: 'Nicht autorisiert' }, { status: 401 })
    }

    if (user.role === 'VIEWER') {
      return NextResponse.json({ error: 'Keine Berechtigung' }, { status: 403 })
    }

    const project = await getProjectWithTenantCheck(id, user)
    if (!project) {
      const exists = await (prisma as any).project.findUnique({ where: { id }, select: { id: true, tenantId: true, ownerId: true } })
      if (!exists) {
        console.warn(`[Features PUT] Project ${id} not in DB`)
        return NextResponse.json({ error: 'Projekt nicht gefunden' }, { status: 404 })
      }
      console.warn(`[Features PUT] Access denied: user=${user.id} tenant=${user.tenantId}, project owner=${exists.ownerId} tenant=${exists.tenantId}`)
      return NextResponse.json({ error: 'Keine Berechtigung für dieses Projekt' }, { status: 403 })
    }

    if (project.isLocked && user.role !== 'SERVER_ADMIN') {
      return NextResponse.json({ error: 'Projekt ist gesperrt' }, { status: 403 })
    }

    const body = await request.json()
    const { features, mapCenter, mapZoom, baseVersion } = body as {
      features: Array<{ id?: string; type: string; geometry: object; properties?: object }>
      mapCenter?: { lng: number; lat: number }
      mapZoom?: number
      baseVersion?: number
    }

    try {
      // ATOMAR + optimistischer Lock in EINER interaktiven Transaktion:
      // - Version prüfen/hochzählen (verhindert Überschreiben durch veralteten Stand)
      // - Features löschen + neu anlegen (kein Totalverlust-Fenster)
      const result = await (prisma as any).$transaction(async (tx: any) => {
        if (typeof baseVersion === 'number') {
          // Nur speichern, wenn die Version noch stimmt (atomar über WHERE-Bedingung)
          const bump = await tx.project.updateMany({
            where: { id, featuresVersion: baseVersion },
            data: { featuresVersion: { increment: 1 } },
          })
          if (bump.count === 0) {
            const conflict: any = new Error('VERSION_CONFLICT')
            conflict.code = 'VERSION_CONFLICT'
            throw conflict
          }
        } else {
          // Kein baseVersion mitgeschickt (Alt-Client/Beacon) → nur hochzählen
          await tx.project.update({ where: { id }, data: { featuresVersion: { increment: 1 } } })
        }

        if (mapCenter && mapZoom !== undefined) {
          await tx.project.update({ where: { id }, data: { mapCenter, mapZoom } })
        }

        await tx.feature.deleteMany({ where: { projectId: id } })
        if (features && features.length > 0) {
          await tx.feature.createMany({
            data: features.map((f: any) => ({
              projectId: id,
              type: f.type,
              geometry: f.geometry,
              properties: f.properties || {},
            })),
          })
        }

        const [updatedFeatures, proj] = await Promise.all([
          tx.feature.findMany({ where: { projectId: id } }),
          tx.project.findUnique({ where: { id }, select: { featuresVersion: true } }),
        ])
        return { features: updatedFeatures, featuresVersion: proj?.featuresVersion ?? 0 }
      }, { timeout: 15000, maxWait: 5000 })

      return NextResponse.json(result)
    } catch (txError: any) {
      if (txError?.code === 'VERSION_CONFLICT') {
        // Konflikt: aktuellen Server-Stand zurückgeben, damit der Client abgleichen kann
        const [currentFeatures, proj] = await Promise.all([
          (prisma as any).feature.findMany({ where: { projectId: id }, orderBy: { createdAt: 'asc' } }),
          (prisma as any).project.findUnique({ where: { id }, select: { featuresVersion: true } }),
        ])
        return NextResponse.json({
          error: 'Der Einsatz wurde zwischenzeitlich geändert.',
          conflict: true,
          features: currentFeatures,
          featuresVersion: proj?.featuresVersion ?? 0,
        }, { status: 409 })
      }
      throw txError
    }
  } catch (error) {
    console.error('Error updating features:', error)
    return NextResponse.json({ error: 'Serverfehler' }, { status: 500 })
  }
}
