import { Router, Response, Request } from 'express';
import { EventGallery, EventGallerySettings } from '../models/index.js';
import { authenticate, requireRole, AuthRequest } from '../middleware/auth.js';

const router = Router();

function slugify(text: string): string {
  return text
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/(^-|-$)/g, '');
}

// Migrate old photos[] to media[] on read
function migrateToMedia(doc: any): any {
  const obj = doc.toObject ? doc.toObject() : { ...doc };
  if ((!obj.media || obj.media.length === 0) && obj.photos && obj.photos.length > 0) {
    obj.media = obj.photos.map((url: string) => ({ url, type: 'image' }));
  }
  return obj;
}

// --- Page-level settings ---

router.get('/settings', async (_req: Request, res: Response): Promise<void> => {
  try {
    let settings = await EventGallerySettings.findOne();
    if (!settings) {
      settings = new EventGallerySettings({});
      await settings.save();
    }
    res.json(settings);
  } catch (error) {
    res.status(500).json({ error: 'Server error' });
  }
});

router.put(
  '/settings',
  authenticate,
  requireRole('admin'),
  async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      let settings = await EventGallerySettings.findOne();
      if (!settings) {
        settings = new EventGallerySettings(req.body);
      } else {
        Object.assign(settings, req.body);
      }
      await settings.save();
      res.json(settings);
    } catch (error) {
      res.status(500).json({ error: 'Server error' });
    }
  }
);

// --- Admin: all events (including drafts), paginated ---

router.get(
  '/admin/all',
  authenticate,
  requireRole('admin', 'editor'),
  async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      const page = parseInt(req.query.page as string) || 1;
      const limit = parseInt(req.query.limit as string) || 20;
      const skip = (page - 1) * limit;

      const total = await EventGallery.countDocuments();
      const raw = await EventGallery.find()
        .sort({ order: 1, eventDate: -1 })
        .skip(skip)
        .limit(limit);

      res.json({
        events: raw.map(migrateToMedia),
        pagination: { page, limit, total, pages: Math.ceil(total / limit) },
      });
    } catch (error) {
      res.status(500).json({ error: 'Server error' });
    }
  }
);

// --- Admin: single event by id (including drafts) ---

router.get(
  '/admin/:id',
  authenticate,
  requireRole('admin', 'editor'),
  async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      const event = await EventGallery.findById(req.params.id);
      if (!event) {
        res.status(404).json({ error: 'Event not found' });
        return;
      }
      res.json(migrateToMedia(event));
    } catch (error) {
      res.status(500).json({ error: 'Server error' });
    }
  }
);

// --- Public: published events ---

router.get('/', async (_req: Request, res: Response): Promise<void> => {
  try {
    const raw = await EventGallery.find({ status: 'published' }).sort({
      order: 1,
      eventDate: -1,
    });
    res.json(raw.map(migrateToMedia));
  } catch (error) {
    res.status(500).json({ error: 'Server error' });
  }
});

// --- Public: single event by slug ---

router.get('/:slug', async (req: Request, res: Response): Promise<void> => {
  try {
    const event = await EventGallery.findOne({
      slug: req.params.slug,
      status: 'published',
    });
    if (!event) {
      res.status(404).json({ error: 'Event not found' });
      return;
    }
    res.json(migrateToMedia(event));
  } catch (error) {
    res.status(500).json({ error: 'Server error' });
  }
});

// --- Admin: create event ---

router.post(
  '/',
  authenticate,
  requireRole('admin', 'editor'),
  async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      const { title, description, coverImage, media, photos, eventDate, status, cardSize, order } = req.body;

      let slug = slugify(title?.en || title?.zh || 'event');
      const existing = await EventGallery.findOne({ slug });
      if (existing) {
        slug = `${slug}-${Date.now()}`;
      }

      const resolvedMedia = media || (photos ? photos.map((url: string) => ({ url, type: 'image' })) : []);

      const event = new EventGallery({
        title,
        slug,
        description,
        coverImage,
        media: resolvedMedia,
        eventDate: eventDate || new Date(),
        status: status || 'draft',
        cardSize: cardSize || 'small',
        order: order ?? 0,
      });
      await event.save();
      res.status(201).json(migrateToMedia(event));
    } catch (error) {
      res.status(500).json({ error: 'Server error' });
    }
  }
);

// --- Admin: batch update order/cardSize ---

router.put(
  '/batch',
  authenticate,
  requireRole('admin', 'editor'),
  async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      type CardSize = 'small' | 'wide' | 'tall' | 'large';
      const { updates } = req.body as {
        updates: Array<{ id: string; order?: number; cardSize?: CardSize }>;
      };
      if (!Array.isArray(updates) || updates.length === 0) {
        res.status(400).json({ error: 'updates array is required' });
        return;
      }
      const ops = updates.map((u) => ({
        updateOne: {
          filter: { _id: u.id },
          update: {
            $set: {
              ...(u.order !== undefined && { order: u.order }),
              ...(u.cardSize !== undefined && { cardSize: u.cardSize }),
            },
          },
        },
      }));
      const result = await EventGallery.bulkWrite(ops as Parameters<typeof EventGallery.bulkWrite>[0]);
      res.json({ modifiedCount: result.modifiedCount });
    } catch (error) {
      res.status(500).json({ error: 'Server error' });
    }
  }
);

// --- Admin: update event ---

router.put(
  '/:id',
  authenticate,
  requireRole('admin', 'editor'),
  async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      const event = await EventGallery.findById(req.params.id);
      if (!event) {
        res.status(404).json({ error: 'Event not found' });
        return;
      }

      const { title, description, coverImage, media, photos, eventDate, status, cardSize, order } = req.body;

      if (title) event.title = title;
      if (description !== undefined) event.description = description;
      if (coverImage !== undefined) event.coverImage = coverImage;
      if (media !== undefined) event.media = media;
      else if (photos !== undefined) event.media = photos.map((url: string) => ({ url, type: 'image' }));
      if (eventDate !== undefined) event.eventDate = eventDate;
      if (status !== undefined) event.status = status;
      if (cardSize !== undefined) event.cardSize = cardSize;
      if (order !== undefined) event.order = order;

      await event.save();
      res.json(migrateToMedia(event));
    } catch (error) {
      res.status(500).json({ error: 'Server error' });
    }
  }
);

// --- Admin: delete event ---

router.delete(
  '/:id',
  authenticate,
  requireRole('admin'),
  async (req: AuthRequest, res: Response): Promise<void> => {
    try {
      const event = await EventGallery.findByIdAndDelete(req.params.id);
      if (!event) {
        res.status(404).json({ error: 'Event not found' });
        return;
      }
      res.json({ message: 'Event deleted' });
    } catch (error) {
      res.status(500).json({ error: 'Server error' });
    }
  }
);

export default router;
