import { Router } from 'express';
import fs from 'fs';
import path from 'path';
import { config } from '../config';
import { prisma } from '../db';
import { forbidden, notFound } from '../lib/errors';
import { param } from '../lib/params';
import { can, loadProjectContext } from '../lib/rbac';
import { AuthedRequest, requireAuth } from '../middleware/auth';

export const attachmentsRouter = Router();
attachmentsRouter.use(requireAuth);

attachmentsRouter.get('/:id/download', async (req: AuthedRequest, res, next) => {
  try {
    const user = req.user!;
    const id = param(req.params.id);
    const att = await prisma.attachment.findUnique({
      where: { id },
      include: {
        task: { select: { id: true, projectId: true, assigneeId: true, contributors: true } },
        bug: {
          select: {
            id: true,
            assigneeId: true,
            reporterId: true,
            parentTask: { select: { projectId: true } },
            assignments: { select: { employeeId: true } },
          },
        },
      },
    });
    if (!att) throw notFound('Attachment not found');

    let projectId = '';
    let isAssignee = false;
    if (att.task) {
      projectId = att.task.projectId;
      isAssignee =
        att.task.assigneeId === user.id ||
        (att.task.contributors || []).includes(user.id);
    } else if (att.bug) {
      projectId = att.bug.parentTask.projectId;
      isAssignee =
        att.bug.assigneeId === user.id ||
        att.bug.reporterId === user.id ||
        (att.bug.assignments || []).some((a) => a.employeeId === user.id);
    } else {
      throw notFound('Attachment not linked');
    }

    const pctx = await loadProjectContext(user.id, projectId);
    if (!can(user, 'view_task', { ...pctx, isTaskAssignee: isAssignee })) {
      throw forbidden('You do not have permission to download this file');
    }

    const abs = path.isAbsolute(att.storagePath)
      ? att.storagePath
      : path.join(config.uploadDir, att.storagePath);
    if (!fs.existsSync(abs)) throw notFound('File missing on disk');

    res.download(abs, att.name);
  } catch (err) {
    next(err);
  }
});
