import type { FastifyInstance } from 'fastify';
import { z } from 'zod';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import { eq } from 'drizzle-orm';
import { users, tenants } from '../../db/schema/index.js';

const loginBody = z.object({
  email: z.string().email(),
  password: z.string().min(1),
});

export default async function authRoutes(fastify: FastifyInstance) {
  fastify.post('/login', async (request, reply) => {
    const body = loginBody.parse(request.body);

    const rows = await fastify.db
      .select({
        id: users.id,
        tenantId: users.tenantId,
        username: users.username,
        email: users.email,
        passwordHash: users.passwordHash,
        role: users.role,
        status: users.status,
        tenantType: tenants.type,
      })
      .from(users)
      .leftJoin(tenants, eq(users.tenantId, tenants.id))
      .where(eq(users.email, body.email))
      .limit(1);

    const user = rows[0];

    if (!user || !(await bcrypt.compare(body.password, user.passwordHash))) {
      return reply.code(401).send({ error: 'Invalid credentials' });
    }

    if (user.status !== 'ACTIVE') {
      return reply.code(403).send({ error: 'Account is inactive' });
    }

    const basePayload = { sub: user.id, tenantId: user.tenantId, role: user.role };
    const accessToken = fastify.jwt.sign({ ...basePayload, type: 'access' as const }, { expiresIn: '15m' });
    const refreshToken = jwt.sign(
      { ...basePayload, type: 'refresh' },
      fastify.config.JWT_REFRESH_SECRET,
      { expiresIn: '7d' }
    );

    reply.setCookie('refreshToken', refreshToken, {
      httpOnly: true,
      secure: fastify.config.NODE_ENV === 'production',
      sameSite: 'strict',
      path: '/api/auth',
      maxAge: 7 * 24 * 60 * 60,
    });

    return {
      accessToken,
      user: {
        id: user.id,
        tenantId: user.tenantId,
        username: user.username,
        email: user.email,
        role: user.role,
        tenantType: user.tenantType ?? null,
      },
    };
  });

  fastify.post('/refresh', async (request, reply) => {
    const token = request.cookies['refreshToken'];
    if (!token) return reply.code(401).send({ error: 'No refresh token' });

    try {
      const payload = jwt.verify(token, fastify.config.JWT_REFRESH_SECRET) as { sub: string; tenantId: string | null; role: string };

      const accessToken = fastify.jwt.sign(
        { sub: payload.sub, tenantId: payload.tenantId, role: payload.role as import('@org/types').UserRole, type: 'access' as const },
        { expiresIn: '15m' }
      );
      return { accessToken };
    } catch {
      return reply.code(401).send({ error: 'Invalid refresh token' });
    }
  });

  fastify.post('/logout', async (_request, reply) => {
    reply.clearCookie('refreshToken', { path: '/api/auth' });
    return { message: 'Logged out' };
  });
}
