import 'server-only'
import { db } from '@/lib/db'
import { readUpload } from '@/lib/images'

const MODE = (process.env.IDENTIFY_MODE || 'off') as 'off' | 'queue' | 'api'

export interface Suggestion {
  name: string
  category: string | null
  brand: string | null
  tags: string[]
  confidence: number
}

// Called from the upload server action right after a Photo row is created.
// In `queue` mode the job sits PENDING for human/Claude-Code review.
// In `api` mode we call Anthropic synchronously and write the suggestion.
export async function enqueueIdentification(photoId: string): Promise<void> {
  if (MODE === 'off') return

  await db.identificationJob.create({
    data: { photoId, status: 'PENDING' },
  })

  if (MODE === 'api') {
    // Fire-and-forget — don't block the upload response on the LLM call.
    runApiIdentification(photoId).catch(err => {
      console.error('Identification failed', err)
    })
  }
}

async function runApiIdentification(photoId: string): Promise<void> {
  const apiKey = process.env.ANTHROPIC_API_KEY
  const model = process.env.IDENTIFY_MODEL || 'claude-haiku-4-5'
  if (!apiKey) {
    await db.identificationJob.update({
      where: { photoId },
      data: {
        status: 'SKIPPED',
        errorMessage: 'ANTHROPIC_API_KEY not set',
        processedAt: new Date(),
      },
    })
    return
  }

  const photo = await db.photo.findUnique({ where: { id: photoId } })
  if (!photo) return

  // Pull every photo on the item — multi-angle shots often carry the brand
  // label or serial plate the primary frame doesn't. Cap at 6 to keep the
  // payload reasonable on a Haiku call.
  const itemPhotos = await db.photo.findMany({
    where: { itemId: photo.itemId },
    orderBy: [{ isPrimary: 'desc' }, { createdAt: 'asc' }],
    take: 6,
  })

  const imageBlocks: Array<{
    type: 'image'
    source: { type: 'base64'; media_type: 'image/webp'; data: string }
  }> = []
  for (const p of itemPhotos) {
    const buf = await readUpload(p.thumbPath)
    if (buf) {
      imageBlocks.push({
        type: 'image',
        source: { type: 'base64', media_type: 'image/webp', data: buf.toString('base64') },
      })
    }
  }

  if (imageBlocks.length === 0) {
    await db.identificationJob.update({
      where: { photoId },
      data: {
        status: 'SKIPPED',
        errorMessage: 'No thumbnails readable',
        processedAt: new Date(),
      },
    })
    return
  }

  const body = {
    model,
    max_tokens: 400,
    messages: [
      {
        role: 'user',
        content: [
          ...imageBlocks,
          {
            type: 'text',
            text: `Identify this household item for an inventory tracker. ${imageBlocks.length > 1 ? `You are looking at ${imageBlocks.length} photos of the SAME item from different angles — combine information across all of them (labels, serial plates, etc.). ` : ''}Respond ONLY with compact JSON: {"name": "...", "category": "...", "brand": "..." or null, "tags": ["...","..."], "confidence": 0.0-1.0}. Name should be a short label, e.g. "Skidsteer loader" or "Cordless drill". Category should be one of: tool, appliance, electronics, furniture, kitchen, outdoor, vehicle, storage, clothing, document, media, art, other. Up to 5 short lowercase tags.`,
          },
        ],
      },
    ],
  }

  try {
    const res = await fetch('https://api.anthropic.com/v1/messages', {
      method: 'POST',
      headers: {
        'content-type': 'application/json',
        'x-api-key': apiKey,
        'anthropic-version': '2023-06-01',
      },
      body: JSON.stringify(body),
    })
    if (!res.ok) {
      const errText = await res.text()
      await db.identificationJob.update({
        where: { photoId },
        data: {
          status: 'SKIPPED',
          errorMessage: `API ${res.status}: ${errText.slice(0, 200)}`,
          processedAt: new Date(),
          model,
        },
      })
      return
    }
    const data = await res.json()
    const text: string = data.content?.[0]?.text || ''
    const match = text.match(/\{[\s\S]*\}/)
    if (!match) throw new Error('No JSON in response')
    const parsed = JSON.parse(match[0]) as Suggestion

    await db.identificationJob.update({
      where: { photoId },
      data: {
        suggestedName: parsed.name?.slice(0, 200) || null,
        suggestedCategory: parsed.category?.slice(0, 50) || null,
        suggestedBrand: parsed.brand?.slice(0, 100) || null,
        suggestedTags: Array.isArray(parsed.tags) ? parsed.tags.slice(0, 8).map(t => String(t).slice(0, 40)) : [],
        confidence: typeof parsed.confidence === 'number' ? parsed.confidence : null,
        model,
        status: 'DONE',
        processedAt: new Date(),
      },
    })
  } catch (err) {
    await db.identificationJob.update({
      where: { photoId },
      data: {
        status: 'SKIPPED',
        errorMessage: err instanceof Error ? err.message.slice(0, 200) : 'unknown',
        processedAt: new Date(),
        model,
      },
    })
  }
}
