import { prisma } from '../db/prisma';
import { nostrService } from './nostr';

export interface ImportPostInput {
  nostrEventId: string;
  naddr?: string | null;
  title: string;
  excerpt?: string | null;
  authorPubkey: string;
  publishedAt?: number | string | null;
  tags?: string[];
  visible?: boolean;
}

// Upserts a blog Post from a Nostr longform event. Shared by the manual import
// endpoint and the submission-approval flow so both produce identical results
// (auto slug, category links from `t` tags, visible by default).
export async function importPostFromNostr(input: ImportPostInput) {
  const { nostrEventId, naddr, title, excerpt, authorPubkey, publishedAt, tags, visible } = input;

  const slugBase = title
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-|-$/g, '');
  const slug = `${slugBase}-${nostrEventId.slice(0, 8)}`;

  const post = await prisma.post.upsert({
    where: { nostrEventId },
    update: {
      title,
      excerpt: excerpt || undefined,
      naddr: naddr || undefined,
    },
    create: {
      nostrEventId,
      naddr: naddr || null,
      title,
      slug,
      excerpt: excerpt || null,
      authorPubkey,
      visible: visible ?? true,
      publishedAt: publishedAt
        ? new Date(typeof publishedAt === 'number' ? publishedAt * 1000 : publishedAt)
        : new Date(),
    },
  });

  if (Array.isArray(tags) && tags.length > 0) {
    const categoryIds: string[] = [];
    for (const tag of tags) {
      const catSlug = tag.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
      if (!catSlug) continue;
      const category = await prisma.category.upsert({
        where: { slug: catSlug },
        update: {},
        create: {
          name: tag.charAt(0).toUpperCase() + tag.slice(1),
          slug: catSlug,
        },
      });
      categoryIds.push(category.id);
    }

    await prisma.postCategory.deleteMany({ where: { postId: post.id } });
    if (categoryIds.length > 0) {
      await prisma.postCategory.createMany({
        data: categoryIds.map((categoryId) => ({
          postId: post.id,
          categoryId,
        })),
      });
    }
  }

  return prisma.post.findUnique({
    where: { id: post.id },
    include: { categories: { include: { category: true } } },
  });
}

export interface SubmissionRef {
  eventId: string | null;
  naddr: string | null;
  title: string;
  authorPubkey: string;
}

// Resolves the Nostr longform event referenced by a submission into a blog
// import payload. Returns null when the event cannot be resolved into something
// publishable (e.g. naddr that no relay can serve and no fallback event id).
export async function resolveSubmissionImport(
  submission: SubmissionRef
): Promise<ImportPostInput | null> {
  const event = submission.naddr
    ? await nostrService.fetchLongformEvent(submission.naddr)
    : submission.eventId
      ? await nostrService.fetchEvent(submission.eventId)
      : null;

  const nostrEventId: string | undefined = event?.id || submission.eventId || undefined;
  if (!nostrEventId) return null;

  const eventTags: string[][] = Array.isArray(event?.tags) ? (event!.tags as string[][]) : [];
  const titleTag = eventTags.find((t) => t[0] === 'title')?.[1];
  const topicTags = eventTags
    .filter((t) => t[0] === 't' && t[1])
    .map((t) => (t[1] as string).toLowerCase());

  const excerpt = ((event?.content as string) || '')
    .slice(0, 200)
    .replace(/[#*_\n]/g, '')
    .trim();

  return {
    nostrEventId,
    naddr: submission.naddr || undefined,
    title: submission.title || titleTag || 'Untitled',
    excerpt: excerpt || undefined,
    authorPubkey: event?.pubkey || submission.authorPubkey,
    publishedAt: event?.created_at ?? null,
    tags: topicTags.length > 0 ? topicTags : undefined,
    visible: true,
  };
}
