import { NextResponse } from 'next/server'
import OpenAI from 'openai'
import { aiRatelimit, getClientIp, checkRateLimit } from '@/lib/ratelimit'
import { sanitizePrompt } from '@/lib/validation'
import { getArchetypeById } from '@/data/archetypes'
import {
  buildPrimePrompt,
  PRIME_TIERS,
  PRIME_GRAINS,
  PRIME_RAINS,
  type PrimeTier,
  type PrimeGrain,
  type PrimeRain,
} from '@/lib/primePrompt'

export const runtime = 'nodejs'
export const dynamic = 'force-dynamic'
export const maxDuration = 120 // Allow up to 120s for OpenAI

const MAX_FILE_MB = 10
const MAX_FILE_BYTES = MAX_FILE_MB * 1024 * 1024

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
})

function parseDataUri(dataUri: string): { mime: string; buffer: Buffer } | null {
  const match = dataUri.match(/^data:(image\/[a-zA-Z0-9+.-]+);base64,(.+)$/)
  if (!match) return null
  return { mime: match[1].toLowerCase(), buffer: Buffer.from(match[2], 'base64') }
}

function normalizeTier(input: string | null): PrimeTier | null {
  if (!input) return 'core'
  const value = input.toLowerCase().trim()
  return PRIME_TIERS.includes(value as PrimeTier) ? (value as PrimeTier) : null
}

function normalizeGrain(input: string | null): PrimeGrain | null {
  if (!input) return 'gritty'
  const value = input.toLowerCase().trim()
  return PRIME_GRAINS.includes(value as PrimeGrain) ? (value as PrimeGrain) : null
}

function normalizeRain(input: string | null): PrimeRain | null {
  if (!input) return 'light'
  const value = input.toLowerCase().trim()
  return PRIME_RAINS.includes(value as PrimeRain) ? (value as PrimeRain) : null
}

export async function POST(request: Request) {
  try {
    // Rate limiting
    const ip = getClientIp(request)
    const { success, error } = await checkRateLimit(aiRatelimit, ip)
    if (!success) return error

    // Parse JSON body
    let body
    try {
      body = await request.json()
    } catch {
      return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 })
    }

    const { image, tier, grain, rain, aura_color, archetype } = body

    // Validate image
    if (!image || typeof image !== 'string' || !image.startsWith('data:image/')) {
      return NextResponse.json({ error: 'Invalid image data' }, { status: 400 })
    }

    const parsed = parseDataUri(image)
    if (!parsed) {
      return NextResponse.json({ error: 'Invalid image data' }, { status: 400 })
    }
    if (!['image/png', 'image/jpeg', 'image/webp', 'image/jpg'].includes(parsed.mime)) {
      return NextResponse.json({ error: 'Unsupported image format' }, { status: 400 })
    }
    if (parsed.buffer.length > MAX_FILE_BYTES) {
      return NextResponse.json({ error: 'Image too large' }, { status: 400 })
    }

    // Normalize parameters
    const normalizedTier = normalizeTier(tier)
    const normalizedGrain = normalizeGrain(grain)
    const normalizedRain = normalizeRain(rain)

    if (!normalizedTier || !normalizedGrain || !normalizedRain) {
      return NextResponse.json({ error: 'Invalid parameters' }, { status: 400 })
    }

    const auraColor = sanitizePrompt(aura_color || 'void-silver').toLowerCase().trim() || 'void-silver'
    const archetypeId = archetype?.toString().toLowerCase().trim()
    const archetypeData = archetypeId ? getArchetypeById(archetypeId) : undefined

    // Build the prompt
    const { prompt } = buildPrimePrompt({
      tier: normalizedTier,
      auraColor,
      archetypeName: archetypeData?.name,
      archetypeModifier: archetypeData?.promptModifier,
      grain: normalizedGrain,
      rain: normalizedRain,
    })

    console.log('=== PRIME SYNC (OpenAI) ===')
    console.log('Prompt length:', prompt.length)
    console.log('===========================')

    // Convert buffer to File for OpenAI
    const uint8Array = new Uint8Array(parsed.buffer)
    const imageFile = new File([uint8Array], 'image.png', { type: 'image/png' })

    // Use OpenAI gpt-image-1 for editing
    const response = await openai.images.edit({
      model: 'gpt-image-1',
      image: imageFile,
      prompt: prompt.substring(0, 3500), // OpenAI has prompt limits
      size: '1024x1024',
      n: 1,
    })

    const resultB64 = response.data?.[0]?.b64_json
    if (!resultB64) {
      return NextResponse.json({ error: 'No image returned from OpenAI' }, { status: 500 })
    }

    const base64 = resultB64

    // Return as data URL
    return NextResponse.json({
      image: `data:image/png;base64,${base64}`
    })

  } catch (error: unknown) {
    console.error('Prime sync error:', error)
    const message = error instanceof Error ? error.message : 'Failed to transform image'
    return NextResponse.json({ error: message }, { status: 500 })
  }
}
