import { Router } from 'express';
import { authenticate } from '../../middleware/auth';
import { requireRoles } from '../../middleware/rbac';
import { Role, ErrorCode } from '@saferoute/constants';
import { prisma } from '../../config/database';
import { sendSuccess, sendError } from '../../utils/response';

export const parentRoutes = Router();

parentRoutes.post('/:studentId/parents', authenticate, requireRoles(Role.OWNER, Role.SCHOOL_TRANSPORT_ADMIN, Role.SCHOOL_PRINCIPAL), async (req, res) => {
  try {
    const { phone, fullName, email, relationship, isPrimary } = req.body;

    let user = await prisma.user.findUnique({ where: { phone } });
    if (!user) { user = await prisma.user.create({ data: { phone, fullName, email } }); }

    const parentRole = await prisma.roleModel.findUnique({ where: { name: Role.PARENT } });
    if (parentRole) {
      const existing = await prisma.userRole.findFirst({ where: { userId: user.id, roleId: parentRole.id } });
      if (!existing) { await prisma.userRole.create({ data: { userId: user.id, roleId: parentRole.id } }); }
    }
    const parent = await prisma.parent.create({
      data: { userId: user.id, studentId: req.params.studentId, relationship: relationship || 'GUARDIAN', isPrimary: isPrimary || false },
    });
    sendSuccess(res, { id: parent.id, fullName: user.fullName, relationship: parent.relationship }, 'Parent added', 201);
  } catch (error) {
    sendError(res, ErrorCode.SERVER_ERROR, 'Failed to add parent.');
  }
});

parentRoutes.get('/:studentId/parents', authenticate, async (req, res) => {
  try {
    const parents = await prisma.parent.findMany({
      where: { studentId: req.params.studentId },
      include: { user: { select: { id: true, fullName: true, phone: true, email: true } } },
    });
    sendSuccess(res, parents.map((p) => ({
      id: p.id, fullName: p.user.fullName, phone: p.user.phone, email: p.user.email,
      relationship: p.relationship, isPrimary: p.isPrimary,
    })));
  } catch (error) {
    sendError(res, ErrorCode.SERVER_ERROR, 'Failed to list parents.');
  }
});

parentRoutes.post('/:studentId/guardians', authenticate, requireRoles(Role.PARENT), async (req, res) => {
  try {
    const { phone, fullName, email, accessLevel } = req.body;
    let user = await prisma.user.findUnique({ where: { phone } });
    if (!user) { user = await prisma.user.create({ data: { phone, fullName, email } }); }
    const guardianRole = await prisma.roleModel.findUnique({ where: { name: Role.GUARDIAN } });
    if (guardianRole) {
      const existing = await prisma.userRole.findFirst({ where: { userId: user.id, roleId: guardianRole.id } });
      if (!existing) { await prisma.userRole.create({ data: { userId: user.id, roleId: guardianRole.id } }); }
    }
    const guardian = await prisma.guardian.create({
      data: { userId: user.id, studentId: req.params.studentId, accessLevel: accessLevel || 'TRIP_ONLY', addedBy: req.user!.userId },
    });
    sendSuccess(res, { id: guardian.id, fullName: user.fullName }, 'Guardian added', 201);
  } catch (error) {
    sendError(res, ErrorCode.SERVER_ERROR, 'Failed to add guardian.');
  }
});

parentRoutes.get('/:studentId/guardians', authenticate, async (req, res) => {
  try {
    const guardians = await prisma.guardian.findMany({
      where: { studentId: req.params.studentId },
      include: { user: { select: { id: true, fullName: true, phone: true } } },
    });
    sendSuccess(res, guardians.map((g) => ({
      id: g.id, fullName: g.user.fullName, phone: g.user.phone, accessLevel: g.accessLevel,
    })));
  } catch (error) {
    sendError(res, ErrorCode.SERVER_ERROR, 'Failed to list guardians.');
  }
});

parentRoutes.patch('/:guardianId/access', authenticate, requireRoles(Role.PARENT), async (req, res) => {
  try {
    const { accessLevel } = req.body;
    if (!['FULL', 'TRIP_ONLY', 'NONE'].includes(accessLevel)) {
      sendError(res, ErrorCode.VALIDATION_ERROR, 'Invalid access level'); return;
    }
    const guardian = await prisma.guardian.update({
      where: { id: req.params.guardianId }, data: { accessLevel },
    });
    sendSuccess(res, { id: guardian.id, accessLevel: guardian.accessLevel }, 'Access updated');
  } catch (error) {
    sendError(res, ErrorCode.SERVER_ERROR, 'Failed to update access.');
  }
});
