import { Router } from 'express';
import type { Request, Response } from 'express';
import { requireRole } from '../../middleware/rbac.middleware';
import { SOCIAL_ROLES } from '../../utils/roles';
import { challengeService } from './challenge.service';
import {
  createChallengeSchema,
  updateChallengeSchema,
  createTeamSchema,
  listChallengesSchema,
} from './challenge.schemas';

const router = Router();

// ── Authenticated (any logged-in user) ───────────────────────────────

/** GET / — list challenges */
router.get('/', async (req: Request, res: Response) => {
  try {
    const { page, limit, status } = listChallengesSchema.parse(req.query);
    const result = await challengeService.listChallenges(page, limit, status);
    res.json(result);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'CHALLENGES_LIST_ERROR' } });
  }
});

/** GET /:id — get challenge detail */
router.get('/:id', async (req: Request, res: Response) => {
  try {
    const challenge = await challengeService.findById(req.params.id as string);
    res.json(challenge);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'CHALLENGE_GET_ERROR' } });
  }
});

/** GET /:id/leaderboard — leaderboard */
router.get('/:id/leaderboard', async (req: Request, res: Response) => {
  try {
    const result = await challengeService.getLeaderboard(req.params.id as string);
    res.json(result);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'LEADERBOARD_ERROR' } });
  }
});

/** GET /:id/my-team — get my team for this challenge */
router.get('/:id/my-team', async (req: Request, res: Response) => {
  try {
    const team = await challengeService.getMyTeam(req.params.id as string, req.user!.id);
    res.json({ team });
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'MY_TEAM_ERROR' } });
  }
});

/** POST /:id/teams — create team */
router.post('/:id/teams', async (req: Request, res: Response) => {
  try {
    const { name } = createTeamSchema.parse(req.body);
    const team = await challengeService.createTeam(req.params.id as string, req.user!.id, name);
    res.status(201).json(team);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'CREATE_TEAM_ERROR' } });
  }
});

/** POST /:id/teams/:teamId/join — join team */
router.post('/:id/teams/:teamId/join', async (req: Request, res: Response) => {
  try {
    const team = await challengeService.joinTeam(req.params.teamId as string, req.user!.id);
    res.json(team);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'JOIN_TEAM_ERROR' } });
  }
});

/** POST /:id/teams/:teamId/leave — leave team */
router.post('/:id/teams/:teamId/leave', async (req: Request, res: Response) => {
  try {
    const result = await challengeService.leaveTeam(req.params.teamId as string, req.user!.id);
    res.json(result);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'LEAVE_TEAM_ERROR' } });
  }
});

/** GET /:id/teams/:teamId — team detail */
router.get('/:id/teams/:teamId', async (req: Request, res: Response) => {
  try {
    const team = await challengeService.getTeamDetail(req.params.teamId as string);
    res.json(team);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'TEAM_DETAIL_ERROR' } });
  }
});

// ── Admin ────────────────────────────────────────────────────────────

const adminRouter = Router();
adminRouter.use(requireRole(...SOCIAL_ROLES));

/** POST /admin — create challenge */
adminRouter.post('/', async (req: Request, res: Response) => {
  try {
    const data = createChallengeSchema.parse(req.body);
    const challenge = await challengeService.create(data, req.user!.id);
    res.status(201).json(challenge);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'CREATE_CHALLENGE_ERROR' } });
  }
});

/** PUT /admin/:id — update challenge */
adminRouter.put('/:id', async (req: Request, res: Response) => {
  try {
    const data = updateChallengeSchema.parse(req.body);
    const challenge = await challengeService.update(req.params.id as string, data);
    res.json(challenge);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'UPDATE_CHALLENGE_ERROR' } });
  }
});

/** DELETE /admin/:id — delete challenge */
adminRouter.delete('/:id', async (req: Request, res: Response) => {
  try {
    const result = await challengeService.delete(req.params.id as string);
    res.json(result);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'DELETE_CHALLENGE_ERROR' } });
  }
});

/** POST /admin/:id/activate — activate challenge */
adminRouter.post('/:id/activate', async (req: Request, res: Response) => {
  try {
    const challenge = await challengeService.activate(req.params.id as string);
    res.json(challenge);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'ACTIVATE_ERROR' } });
  }
});

/** POST /admin/:id/complete — force complete */
adminRouter.post('/:id/complete', async (req: Request, res: Response) => {
  try {
    const challenge = await challengeService.complete(req.params.id as string);
    res.json(challenge);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'COMPLETE_ERROR' } });
  }
});

/** POST /admin/:id/cancel — cancel challenge */
adminRouter.post('/:id/cancel', async (req: Request, res: Response) => {
  try {
    const challenge = await challengeService.cancel(req.params.id as string);
    res.json(challenge);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'CANCEL_ERROR' } });
  }
});

/** POST /admin/:id/rescore — force rescore */
adminRouter.post('/:id/rescore', async (req: Request, res: Response) => {
  try {
    const result = await challengeService.rescore(req.params.id as string);
    res.json(result);
  } catch (err: any) {
    res.status(err.statusCode || 500).json({ error: { message: err.message, code: 'RESCORE_ERROR' } });
  }
});

router.use('/admin', adminRouter);

export { router as challengeRouter };
