import { Router, Request, Response } from 'express';
import { prisma } from '../db/prisma';
import { requireAuth, requireRole } from '../middleware/auth';
import { nostrService } from '../services/nostr';

const router = Router();

router.get('/', async (req: Request, res: Response) => {
  try {
    const page = parseInt(req.query.page as string) || 1;
    const limit = parseInt(req.query.limit as string) || 20;
    const category = req.query.category as string | undefined;
    const skip = (page - 1) * limit;

    const where: any = { visible: true };
    if (category) {
      where.categories = {
        some: { category: { slug: category } },
      };
    }

    const [posts, total] = await Promise.all([
      prisma.post.findMany({
        where,
        include: {
          categories: { include: { category: true } },
        },
        orderBy: { publishedAt: 'desc' },
        skip,
        take: limit,
      }),
      prisma.post.count({ where }),
    ]);

    res.json({
      posts,
      pagination: { page, limit, total, pages: Math.ceil(total / limit) },
    });
  } catch (err) {
    console.error('List posts error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

router.get('/:slug', async (req: Request, res: Response) => {
  try {
    const post = await prisma.post.findUnique({
      where: { slug: req.params.slug as string },
      include: {
        categories: { include: { category: true } },
      },
    });

    if (!post) {
      res.status(404).json({ error: 'Post not found' });
      return;
    }

    res.json(post);
  } catch (err) {
    console.error('Get post error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

router.post(
  '/import',
  requireAuth,
  requireRole(['ADMIN', 'MODERATOR']),
  async (req: Request, res: Response) => {
    try {
      const { eventId, naddr } = req.body;
      if (!eventId && !naddr) {
        res.status(400).json({ error: 'eventId or naddr is required' });
        return;
      }

      let event: any = null;
      if (naddr) {
        event = await nostrService.fetchLongformEvent(naddr);
      } else if (eventId) {
        event = await nostrService.fetchEvent(eventId);
      }

      if (!event) {
        res.status(404).json({ error: 'Event not found on relays' });
        return;
      }

      const titleTag = event.tags?.find((t: string[]) => t[0] === 'title');
      const title = titleTag?.[1] || 'Untitled';

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

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

      const post = await prisma.post.upsert({
        where: { nostrEventId: event.id },
        update: {
          title,
          content: event.content,
          excerpt,
        },
        create: {
          nostrEventId: event.id,
          title,
          slug,
          content: event.content,
          excerpt,
          authorPubkey: event.pubkey,
          publishedAt: new Date(event.created_at * 1000),
        },
      });

      res.json(post);
    } catch (err) {
      console.error('Import post error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.patch(
  '/:id',
  requireAuth,
  requireRole(['ADMIN', 'MODERATOR']),
  async (req: Request, res: Response) => {
    try {
      const { title, slug, excerpt, featured, visible, categories } = req.body;

      const post = await prisma.post.findUnique({ where: { id: req.params.id as string } });
      if (!post) {
        res.status(404).json({ error: 'Post not found' });
        return;
      }

      const updateData: any = {};
      if (title !== undefined) updateData.title = title;
      if (slug !== undefined) updateData.slug = slug;
      if (excerpt !== undefined) updateData.excerpt = excerpt;
      if (featured !== undefined) updateData.featured = featured;
      if (visible !== undefined) updateData.visible = visible;

      const updated = await prisma.post.update({
        where: { id: req.params.id as string },
        data: updateData,
      });

      if (categories && Array.isArray(categories)) {
        await prisma.postCategory.deleteMany({
          where: { postId: post.id },
        });
        await prisma.postCategory.createMany({
          data: categories.map((categoryId: string) => ({
            postId: post.id,
            categoryId,
          })),
        });
      }

      const result = await prisma.post.findUnique({
        where: { id: updated.id },
        include: { categories: { include: { category: true } } },
      });

      res.json(result);
    } catch (err) {
      console.error('Update post error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.get('/:slug/reactions', async (req: Request, res: Response) => {
  try {
    const post = await prisma.post.findUnique({ where: { slug: req.params.slug as string } });
    if (!post) {
      res.status(404).json({ error: 'Post not found' });
      return;
    }

    const reactions = await nostrService.fetchReactions(post.nostrEventId);
    res.json({ count: reactions.length, reactions });
  } catch (err) {
    console.error('Get reactions error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

router.get('/:slug/replies', async (req: Request, res: Response) => {
  try {
    const post = await prisma.post.findUnique({ where: { slug: req.params.slug as string } });
    if (!post) {
      res.status(404).json({ error: 'Post not found' });
      return;
    }

    const [replies, hiddenContent, blockedPubkeys] = await Promise.all([
      nostrService.fetchReplies(post.nostrEventId),
      prisma.hiddenContent.findMany({ select: { nostrEventId: true } }),
      prisma.blockedPubkey.findMany({ select: { pubkey: true } }),
    ]);

    const hiddenIds = new Set(hiddenContent.map((h) => h.nostrEventId));
    const blockedKeys = new Set(blockedPubkeys.map((b) => b.pubkey));

    const filtered = replies.filter(
      (r) => !hiddenIds.has(r.id) && !blockedKeys.has(r.pubkey)
    );

    res.json({ count: filtered.length, replies: filtered });
  } catch (err) {
    console.error('Get replies error:', err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

router.delete(
  '/:id',
  requireAuth,
  requireRole(['ADMIN']),
  async (req: Request, res: Response) => {
    try {
      const post = await prisma.post.findUnique({ where: { id: req.params.id as string } });
      if (!post) {
        res.status(404).json({ error: 'Post not found' });
        return;
      }

      await prisma.post.delete({ where: { id: req.params.id as string } });
      res.json({ success: true });
    } catch (err) {
      console.error('Delete post error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

export default router;
