import { Router } from 'express';
import { authenticate } from '../../middleware/auth.middleware';
import { validate } from '../../middleware/validate';
import { sharedCalendarService } from './shared-calendar.service';
import {
  createSharedViewSchema,
  updateSharedViewSchema,
  inviteMembersSchema,
  respondToInviteSchema,
  createCommentSchema,
  createReactionSchema,
  shareItemSchema,
  availabilityQuerySchema,
  dateRangeQuerySchema,
} from './shared-calendar.schemas';

const router = Router();

// =========================================================================
// Public route (no auth)
// =========================================================================

router.get('/public/:shareToken', async (req, res, next) => {
  try {
    const { shareToken } = req.params as { shareToken: string };
    const { startDate, endDate } = req.query as { startDate: string; endDate: string };
    if (!startDate || !endDate) {
      res.status(400).json({ error: { message: 'startDate and endDate are required' } });
      return;
    }
    const result = await sharedCalendarService.getPublicView(shareToken, startDate, endDate);
    res.json(result);
  } catch (error) {
    next(error);
  }
});

// =========================================================================
// Authenticated routes
// =========================================================================

router.use(authenticate);

// --- Shared View CRUD ---

router.get('/', async (req, res, next) => {
  try {
    const views = await sharedCalendarService.listSharedViews(req.user!.id);
    res.json({ views });
  } catch (error) {
    next(error);
  }
});

router.post('/', validate(createSharedViewSchema), async (req, res, next) => {
  try {
    const view = await sharedCalendarService.createSharedView(req.user!.id, req.body);
    res.status(201).json({ view });
  } catch (error) {
    next(error);
  }
});

router.patch('/:id', validate(updateSharedViewSchema), async (req, res, next) => {
  try {
    const view = await sharedCalendarService.updateSharedView(
      req.user!.id,
      req.params.id as string,
      req.body,
    );
    res.json({ view });
  } catch (error) {
    next(error);
  }
});

router.delete('/:id', async (req, res, next) => {
  try {
    await sharedCalendarService.deleteSharedView(req.user!.id, req.params.id as string);
    res.json({ success: true });
  } catch (error) {
    next(error);
  }
});

// --- Member Management ---

router.post('/:id/invite', validate(inviteMembersSchema), async (req, res, next) => {
  try {
    const results = await sharedCalendarService.inviteMembers(
      req.user!.id,
      req.params.id as string,
      req.body.userIds,
    );
    res.json({ results });
  } catch (error) {
    next(error);
  }
});

router.patch('/:id/respond', validate(respondToInviteSchema), async (req, res, next) => {
  try {
    const member = await sharedCalendarService.respondToInvite(
      req.user!.id,
      req.params.id as string,
      req.body.status,
    );
    res.json({ member });
  } catch (error) {
    next(error);
  }
});

router.delete('/:id/leave', async (req, res, next) => {
  try {
    await sharedCalendarService.leaveView(req.user!.id, req.params.id as string);
    res.json({ success: true });
  } catch (error) {
    next(error);
  }
});

router.get('/:id/members', async (req, res, next) => {
  try {
    const members = await sharedCalendarService.getMembers(
      req.params.id as string,
      req.user!.id,
    );
    res.json({ members });
  } catch (error) {
    next(error);
  }
});

// --- Merged Items ---

router.get('/:id/items', validate(dateRangeQuerySchema, 'query'), async (req, res, next) => {
  try {
    const { startDate, endDate } = req.query as { startDate: string; endDate: string };
    const items = await sharedCalendarService.getSharedViewItems(
      req.params.id as string,
      req.user!.id,
      startDate,
      endDate,
    );
    res.json({ items });
  } catch (error) {
    next(error);
  }
});

// --- Comments ---

router.get('/:id/comments', async (req, res, next) => {
  try {
    const date = req.query.date as string;
    if (!date) {
      res.status(400).json({ error: { message: 'date query parameter is required' } });
      return;
    }
    const comments = await sharedCalendarService.getComments(
      req.params.id as string,
      req.user!.id,
      date,
    );
    res.json({ comments });
  } catch (error) {
    next(error);
  }
});

router.post('/:id/comments', validate(createCommentSchema), async (req, res, next) => {
  try {
    const comment = await sharedCalendarService.createComment(
      req.params.id as string,
      req.user!.id,
      req.body,
    );
    res.status(201).json({ comment });
  } catch (error) {
    next(error);
  }
});

router.delete('/:id/comments/:commentId', async (req, res, next) => {
  try {
    await sharedCalendarService.deleteComment(
      req.params.commentId as string,
      req.user!.id,
    );
    res.json({ success: true });
  } catch (error) {
    next(error);
  }
});

// --- Reactions ---

router.post('/:id/reactions', validate(createReactionSchema), async (req, res, next) => {
  try {
    const reaction = await sharedCalendarService.addReaction(
      req.params.id as string,
      req.user!.id,
      req.body,
    );
    res.status(201).json({ reaction });
  } catch (error) {
    next(error);
  }
});

router.delete('/:id/reactions/:reactionId', async (req, res, next) => {
  try {
    await sharedCalendarService.removeReaction(
      req.params.reactionId as string,
      req.user!.id,
    );
    res.json({ success: true });
  } catch (error) {
    next(error);
  }
});

// --- Availability ---

router.get('/:id/availability', validate(availabilityQuerySchema, 'query'), async (req, res, next) => {
  try {
    const { start, end, dayStart, dayEnd, slotDuration } = req.query as unknown as {
      start: string; end: string; dayStart: string; dayEnd: string; slotDuration: number;
    };
    const result = await sharedCalendarService.findAvailability(
      req.params.id as string,
      req.user!.id,
      start,
      end,
      dayStart,
      dayEnd,
      Number(slotDuration),
    );
    res.json(result);
  } catch (error) {
    next(error);
  }
});

// --- Share Token ---

router.post('/:id/share-token', async (req, res, next) => {
  try {
    const result = await sharedCalendarService.generateShareToken(
      req.user!.id,
      req.params.id as string,
    );
    res.json(result);
  } catch (error) {
    next(error);
  }
});

// --- Item Sharing & Friend Calendar ---

router.post('/items/:id/share', validate(shareItemSchema), async (req, res, next) => {
  try {
    const results = await sharedCalendarService.shareItemWithFriends(
      req.user!.id,
      req.params.id as string,
      req.body.friendIds,
      req.body.message,
    );
    res.json({ results });
  } catch (error) {
    next(error);
  }
});

router.get('/user/:userId', validate(dateRangeQuerySchema, 'query'), async (req, res, next) => {
  try {
    const { startDate, endDate } = req.query as { startDate: string; endDate: string };
    const items = await sharedCalendarService.getFriendPublicCalendar(
      req.user!.id,
      req.params.userId as string,
      startDate,
      endDate,
    );
    res.json({ items });
  } catch (error) {
    next(error);
  }
});

export default router;
