import { Router, Request, Response } from 'express';
import { prisma } from '../db/prisma';
import { requireAuth, requires } from '../middleware/auth';
import { DEFAULT_ORGANIZER_SLUG } from '../constants/organizer';
import { respondIfOrganizerMigrationNeeded } from '../lib/prismaMigrationHint';

const router = Router();

const meetupInclude = { organizer: true } as const;

function incrementTitle(title: string): string {
  const match = title.match(/^(.*#)(\d+)(.*)$/);
  if (match) {
    const num = parseInt(match[2], 10);
    return `${match[1]}${num + 1}${match[3]}`;
  }
  return `${title} (copy)`;
}

async function resolveOrganizerIdForCreate(organizerId: unknown): Promise<string | null> {
  if (typeof organizerId === 'string' && organizerId.trim()) {
    return organizerId;
  }
  const def = await prisma.organizer.findUnique({ where: { slug: DEFAULT_ORGANIZER_SLUG } });
  return def?.id ?? null;
}

router.get('/', async (req: Request, res: Response) => {
  try {
    const status = req.query.status as string | undefined;
    const admin = req.query.admin === 'true';
    const organizerSlug = req.query.organizerSlug as string | undefined;
    const where: Record<string, unknown> = {};
    if (status) where.status = status;
    if (!admin) where.visibility = 'PUBLIC';

    if (organizerSlug) {
      const org = await prisma.organizer.findUnique({ where: { slug: organizerSlug } });
      if (!org) {
        res.status(404).json({ error: 'Organizer not found' });
        return;
      }
      where.organizerId = org.id;
    }

    const meetups = await prisma.meetup.findMany({
      where,
      orderBy: { date: 'asc' },
      include: meetupInclude,
    });

    res.json(meetups);
  } catch (err) {
    console.error('List meetups error:', err);
    if (respondIfOrganizerMigrationNeeded(err, res)) return;
    res.status(500).json({ error: 'Internal server error' });
  }
});

router.get('/:id', async (req: Request, res: Response) => {
  try {
    const meetup = await prisma.meetup.findUnique({
      where: { id: req.params.id as string },
      include: meetupInclude,
    });

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

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

router.post(
  '/',
  requireAuth,
  requires('events.create'),
  async (req: Request, res: Response) => {
    try {
      const {
        title,
        description,
        date,
        time,
        location,
        link,
        status,
        featured,
        imageId,
        visibility,
        organizerId,
      } = req.body;

      if (!title || !description || !date || !time || !location) {
        res
          .status(400)
          .json({ error: 'title, description, date, time, and location are required' });
        return;
      }

      const resolvedOrganizerId = await resolveOrganizerIdForCreate(organizerId);
      if (!resolvedOrganizerId) {
        res.status(500).json({ error: 'Default organizer is not configured' });
        return;
      }

      const meetup = await prisma.meetup.create({
        data: {
          title,
          description,
          date,
          time,
          location,
          link: link || null,
          imageId: imageId || null,
          status: status || 'DRAFT',
          featured: featured || false,
          visibility: visibility || 'PUBLIC',
          organizerId: resolvedOrganizerId,
        },
        include: meetupInclude,
      });

      res.status(201).json(meetup);
    } catch (err) {
      console.error('Create meetup error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.post(
  '/bulk',
  requireAuth,
  requires('events.edit'),
  async (req: Request, res: Response) => {
    try {
      const { action, ids } = req.body as { action: string; ids: string[] };

      if (!action || !Array.isArray(ids) || ids.length === 0) {
        res.status(400).json({ error: 'action and ids are required' });
        return;
      }

      if (action === 'delete') {
        await prisma.meetup.deleteMany({ where: { id: { in: ids } } });
        res.json({ success: true, affected: ids.length });
        return;
      }

      if (action === 'publish') {
        await prisma.meetup.updateMany({
          where: { id: { in: ids } },
          data: { status: 'PUBLISHED' },
        });
        res.json({ success: true, affected: ids.length });
        return;
      }

      if (action === 'duplicate') {
        const originals = await prisma.meetup.findMany({ where: { id: { in: ids } } });
        const created = await Promise.all(
          originals.map((m) =>
            prisma.meetup.create({
              data: {
                title: incrementTitle(m.title),
                description: m.description,
                date: '',
                time: '',
                location: m.location,
                link: m.link || null,
                imageId: m.imageId || null,
                status: 'DRAFT',
                featured: false,
                visibility: 'PUBLIC',
                organizerId: m.organizerId,
              },
              include: meetupInclude,
            })
          )
        );
        res.json(created);
        return;
      }

      res.status(400).json({ error: 'Unknown action' });
    } catch (err) {
      console.error('Bulk meetup error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.post(
  '/:id/duplicate',
  requireAuth,
  requires('events.create'),
  async (req: Request, res: Response) => {
    try {
      const original = await prisma.meetup.findUnique({ where: { id: req.params.id as string } });
      if (!original) {
        res.status(404).json({ error: 'Meetup not found' });
        return;
      }

      const duplicate = await prisma.meetup.create({
        data: {
          title: incrementTitle(original.title),
          description: original.description,
          date: '',
          time: '',
          location: original.location,
          link: original.link || null,
          imageId: original.imageId || null,
          status: 'DRAFT',
          featured: false,
          visibility: 'PUBLIC',
          organizerId: original.organizerId,
        },
        include: meetupInclude,
      });

      res.status(201).json(duplicate);
    } catch (err) {
      console.error('Duplicate meetup error:', err);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
);

router.patch(
  '/:id',
  requireAuth,
  requires('events.edit'),
  async (req: Request, res: Response) => {
    try {
      const meetup = await prisma.meetup.findUnique({
        where: { id: req.params.id as string },
      });
      if (!meetup) {
        res.status(404).json({ error: 'Meetup not found' });
        return;
      }

      const {
        title,
        description,
        date,
        time,
        location,
        link,
        status,
        featured,
        imageId,
        visibility,
        organizerId,
      } = req.body;

      const updateData: Record<string, unknown> = {};
      if (title !== undefined) updateData.title = title;
      if (description !== undefined) updateData.description = description;
      if (date !== undefined) updateData.date = date;
      if (time !== undefined) updateData.time = time;
      if (location !== undefined) updateData.location = location;
      if (link !== undefined) updateData.link = link;
      if (status !== undefined) updateData.status = status;
      if (featured !== undefined) updateData.featured = featured;
      if (imageId !== undefined) updateData.imageId = imageId;
      if (visibility !== undefined) updateData.visibility = visibility;
      if (organizerId !== undefined) updateData.organizerId = organizerId;

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

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

router.delete(
  '/:id',
  requireAuth,
  requires('events.delete'),
  async (req: Request, res: Response) => {
    try {
      const meetup = await prisma.meetup.findUnique({
        where: { id: req.params.id as string },
      });
      if (!meetup) {
        res.status(404).json({ error: 'Meetup not found' });
        return;
      }

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

export default router;
