import { NextRequest, NextResponse } from "next/server";
import { requireFamily } from "@/lib/auth";
import { sql } from "@/db";
import { toProxyUrl } from "@/lib/r2-proxy";

function getBaseUrl() {
  const pub = process.env.R2_PUBLIC_URL;
  const id = process.env.R2_ACCOUNT_ID;
  return pub || `https://pub-${id}.r2.dev`;
}

function toMemoryDto(m: Record<string, unknown>, baseUrl: string) {
  const rawUrl = `${baseUrl}/${m.r2_key}`;
  const rawThumb = m.r2_thumbnail_key ? `${baseUrl}/${m.r2_thumbnail_key}` : null;
  return {
    id: m.id,
    key: m.r2_key,
    url: toProxyUrl(rawUrl) ?? rawUrl,
    thumbnailUrl: toProxyUrl(rawThumb),
    sizeBytes: m.size_bytes,
    mimeType: m.mime_type,
    title: m.title,
    description: m.description,
    takenAt: m.taken_at,
    visionCaption: m.vision_caption,
    visionTags: m.vision_tags,
    isPrivate: m.is_private,
    processingStatus: m.processing_status,
    createdAt: m.created_at,
    updatedAt: m.updated_at,
  };
}

// GET /api/memories?childId=&limit=30&cursor=
export async function GET(req: NextRequest) {
  const auth = await requireFamily();
  if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });

  const familyId = auth.session!.familyId!;
  const { searchParams } = new URL(req.url);
  const childId = searchParams.get("childId");
  const limit = Math.min(parseInt(searchParams.get("limit") || "30"), 100);
  const cursor = searchParams.get("cursor"); // ISO timestamp for pagination

  // Orphaned row definition:
  //   - processing_status = 'failed'  → confirm step ran, HeadObject found nothing in R2
  //   - processing_status = 'uploading' older than 30 min → browser closed/connection dropped
  //     before the upload and confirm steps completed; file never reached R2.
  // These rows have no R2 object behind them. Delete them silently so they stop
  // inflating the count and making the grid look broken.
  sql`
    DELETE FROM memories
    WHERE family_id = ${familyId}
      AND (
        processing_status = 'failed'
        OR (processing_status = 'uploading' AND created_at < NOW() - INTERVAL '30 minutes')
      )
  `.catch(() => {}); // fire-and-forget, don't block the response

  let rows;
  if (childId) {
    rows = cursor
      ? await sql`
          SELECT * FROM memories
          WHERE family_id = ${familyId} AND child_id = ${childId}
            AND created_at < ${cursor}
            AND processing_status NOT IN ('failed')
            AND (processing_status != 'uploading' OR created_at > NOW() - INTERVAL '30 minutes')
          ORDER BY created_at DESC LIMIT ${limit}`
      : await sql`
          SELECT * FROM memories
          WHERE family_id = ${familyId} AND child_id = ${childId}
            AND processing_status NOT IN ('failed')
            AND (processing_status != 'uploading' OR created_at > NOW() - INTERVAL '30 minutes')
          ORDER BY created_at DESC LIMIT ${limit}`;
  } else {
    rows = cursor
      ? await sql`
          SELECT * FROM memories
          WHERE family_id = ${familyId}
            AND created_at < ${cursor}
            AND processing_status NOT IN ('failed')
            AND (processing_status != 'uploading' OR created_at > NOW() - INTERVAL '30 minutes')
          ORDER BY created_at DESC LIMIT ${limit}`
      : await sql`
          SELECT * FROM memories
          WHERE family_id = ${familyId}
            AND processing_status NOT IN ('failed')
            AND (processing_status != 'uploading' OR created_at > NOW() - INTERVAL '30 minutes')
          ORDER BY created_at DESC LIMIT ${limit}`;
  }

  const baseUrl = getBaseUrl();
  const items = rows.map(m => toMemoryDto(m, baseUrl));
  const nextCursor = rows.length === limit ? rows[rows.length - 1].created_at : null;

  return NextResponse.json({ success: true, items, nextCursor });
}
