import { NextResponse } from 'next/server'
import { db } from '@/lib/db'
import { checkAgentAuth, checkCallbackSecret } from '@/lib/agent-auth'
import { appleOwnerId } from '@/lib/owner'

export const runtime = 'nodejs'

function toDate(v: unknown): Date | null {
  if (typeof v !== 'string' || !v.trim()) return null
  const d = new Date(v)
  return isNaN(d.getTime()) ? null : d
}

interface RemIn { externalId: string; listId?: string; listName?: string; title?: string; notes?: string | null; completed?: boolean; priority?: number; dueDate?: string | null }
interface EvIn { externalId: string; calendarName?: string; title?: string; notes?: string | null; location?: string | null; startsAt?: string; endsAt?: string | null; allDay?: boolean; recurrence?: string | null }

// POST /api/agent/mirror — full Apple → app sync (read mirror, M4a).
// Body: { reminders: RemIn[], events: EvIn[] }. Upserts by externalId and
// reconciles (removes mirrored rows no longer present). Capture-created rows
// share the same externalId so they merge rather than duplicate.
export async function POST(req: Request) {
  if (!checkAgentAuth(req)) return NextResponse.json({ error: 'unauthorized' }, { status: 401 })
  if (!checkCallbackSecret(req)) return NextResponse.json({ error: 'bad callback secret' }, { status: 403 })

  const body = await req.json().catch(() => null)
  const reminders: RemIn[] = Array.isArray(body?.reminders) ? body.reminders : []
  const events: EvIn[] = Array.isArray(body?.events) ? body.events : []

  // EventKit runs under ONE iCloud account, so everything this route touches —
  // upserts and, crucially, the reconcile below — belongs to that one account.
  const ownerId = await appleOwnerId()

  let listsUpserted = 0
  const seenReminderIds: string[] = []
  for (const r of reminders) {
    if (!r.externalId || !r.title) continue
    let listId: string | undefined
    if (r.listId && r.listName) {
      const list = await db.reminderList.upsert({
        where: { externalId: r.listId },
        update: { name: r.listName },
        create: { ownerId, externalId: r.listId, name: r.listName },
      })
      listId = list.id
      listsUpserted++
    }
    const data = {
      listId,
      title: r.title,
      notes: r.notes ?? null,
      completed: !!r.completed,
      priority: typeof r.priority === 'number' ? r.priority : null,
      dueDate: toDate(r.dueDate),
      syncState: 'SYNCED' as const,
      lastSyncedAt: new Date(),
    }
    await db.reminder.upsert({
      where: { externalId: r.externalId },
      update: data, // note: does NOT touch sourceId, preserving capture links
      create: { ownerId, externalId: r.externalId, ...data },
    })
    seenReminderIds.push(r.externalId)
  }

  const seenEventIds: string[] = []
  for (const e of events) {
    const start = toDate(e.startsAt)
    if (!e.externalId || !e.title || !start) continue
    const data = {
      calendar: e.calendarName ?? null,
      title: e.title,
      notes: e.notes ?? null,
      location: e.location ?? null,
      startsAt: start,
      endsAt: toDate(e.endsAt),
      allDay: !!e.allDay,
      recurrence: e.recurrence ?? null,
      syncState: 'SYNCED' as const,
      lastSyncedAt: new Date(),
    }
    await db.calendarEvent.upsert({
      where: { externalId: e.externalId },
      update: data,
      create: { ownerId, externalId: e.externalId, ...data },
    })
    seenEventIds.push(e.externalId)
  }

  // Reconcile: drop mirrored rows (have an externalId) no longer present in
  // Apple. Guard against wiping everything if a dump came back empty.
  // Scoped to ownerId: without it this reconcile deletes rows belonging to
  // accounts that have no Apple sync at all — they have no EventKit
  // counterpart, so every one of them looks like a deletion. See PLAN.md §11.
  let removed = 0
  if (reminders.length > 0) {
    const res = await db.reminder.deleteMany({
      where: { ownerId, externalId: { not: null, notIn: seenReminderIds } },
    })
    removed += res.count
  }
  if (events.length > 0) {
    const res = await db.calendarEvent.deleteMany({
      where: { ownerId, externalId: { not: null, notIn: seenEventIds } },
    })
    removed += res.count
  }

  await db.agentRun.create({
    data: {
      kind: 'mirror',
      finishedAt: new Date(),
      status: 'SUCCEEDED',
      counts: { reminders: seenReminderIds.length, events: seenEventIds.length, lists: listsUpserted, removed },
    },
  })

  return NextResponse.json({ ok: true, reminders: seenReminderIds.length, events: seenEventIds.length, removed })
}
