import { SimplePool, nip19 } from 'nostr-tools';
import { prisma } from '../db/prisma';

const pool = new SimplePool();

async function getRelayUrls(): Promise<string[]> {
  const relays = await prisma.relay.findMany({
    where: { active: true },
    orderBy: { priority: 'asc' },
  });
  return relays.map((r) => r.url);
}

export const nostrService = {
  async fetchEvent(eventId: string, skipCache = false) {
    if (!skipCache) {
      const cached = await prisma.nostrEventCache.findUnique({
        where: { eventId },
      });
      if (cached) {
        return {
          id: cached.eventId,
          kind: cached.kind,
          pubkey: cached.pubkey,
          content: cached.content,
          tags: JSON.parse(cached.tags),
          created_at: cached.createdAt,
        };
      }
    }

    const relays = await getRelayUrls();
    if (relays.length === 0) return null;

    try {
      const event = await pool.get(relays, { ids: [eventId] });
      if (!event) return null;

      await prisma.nostrEventCache.upsert({
        where: { eventId: event.id },
        update: {
          content: event.content,
          tags: JSON.stringify(event.tags),
        },
        create: {
          eventId: event.id,
          kind: event.kind,
          pubkey: event.pubkey,
          content: event.content,
          tags: JSON.stringify(event.tags),
          createdAt: event.created_at,
        },
      });

      return event;
    } catch (err) {
      console.error('Failed to fetch event:', err);
      return null;
    }
  },

  async fetchLongformEvent(naddrStr: string) {
    let decoded: nip19.AddressPointer;
    try {
      const result = nip19.decode(naddrStr);
      if (result.type !== 'naddr') return null;
      decoded = result.data;
    } catch {
      return null;
    }

    const relays = decoded.relays?.length
      ? decoded.relays
      : await getRelayUrls();
    if (relays.length === 0) return null;

    try {
      const event = await pool.get(relays, {
        kinds: [decoded.kind],
        authors: [decoded.pubkey],
        '#d': [decoded.identifier],
      });
      if (!event) return null;

      await prisma.nostrEventCache.upsert({
        where: { eventId: event.id },
        update: {
          content: event.content,
          tags: JSON.stringify(event.tags),
        },
        create: {
          eventId: event.id,
          kind: event.kind,
          pubkey: event.pubkey,
          content: event.content,
          tags: JSON.stringify(event.tags),
          createdAt: event.created_at,
        },
      });

      return event;
    } catch (err) {
      console.error('Failed to fetch longform event:', err);
      return null;
    }
  },

  async fetchReactions(eventId: string) {
    const relays = await getRelayUrls();
    if (relays.length === 0) return [];

    try {
      const events = await pool.querySync(relays, {
        kinds: [7],
        '#e': [eventId],
      });
      return events;
    } catch (err) {
      console.error('Failed to fetch reactions:', err);
      return [];
    }
  },

  async fetchReplies(eventId: string) {
    const relays = await getRelayUrls();
    if (relays.length === 0) return [];

    try {
      const events = await pool.querySync(relays, {
        kinds: [1],
        '#e': [eventId],
      });
      return events;
    } catch (err) {
      console.error('Failed to fetch replies:', err);
      return [];
    }
  },

  async getRelays() {
    return prisma.relay.findMany({
      where: { active: true },
      orderBy: { priority: 'asc' },
    });
  },
};
