import fp from 'fastify-plugin';
import jwt from '@fastify/jwt';
import cookie from '@fastify/cookie';
import type { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import type { UserRole } from '@org/types';

declare module '@fastify/jwt' {
  interface FastifyJWT {
    payload: {
      sub: string;
      tenantId: string | null;
      role: UserRole;
      type: 'access' | 'refresh';
    };
    user: {
      sub: string;
      tenantId: string | null;
      role: UserRole;
      type: 'access' | 'refresh';
    };
  }
}

export default fp(async function authPlugin(fastify: FastifyInstance) {
  fastify.register(cookie);
  fastify.register(jwt, {
    secret: fastify.config.JWT_SECRET,
    sign: { expiresIn: '15m' },
  });

  fastify.decorate('authenticate', async (request: FastifyRequest, reply: FastifyReply) => {
    try {
      await request.jwtVerify();
      if (request.user.type !== 'access') {
        return reply.code(401).send({ error: 'Invalid token type' });
      }
    } catch {
      return reply.code(401).send({ error: 'Unauthorized' });
    }
  });

  fastify.decorate(
    'authorize',
    (roles: UserRole[]) => async (request: FastifyRequest, reply: FastifyReply) => {
      if (!roles.includes(request.user.role)) {
        return reply.code(403).send({ error: 'Forbidden' });
      }
    }
  );
});

declare module 'fastify' {
  interface FastifyInstance {
    authenticate: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
    authorize: (roles: UserRole[]) => (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
  }
}
