import { FastifyInstance } from 'fastify';
import { prisma } from '../../config/database.js';
import { registerSchema, loginSchema } from '../middleware/validate.js';
import { authMiddleware, generateTokens, JwtPayload } from '../middleware/auth.middleware.js';
import { hashPassword, verifyPassword, generateApiKey, generateApiSecret, generateSlug, generateWebhookSecret } from '../../utils/crypto.js';
import { successResponse, errorResponse } from '../../utils/helpers.js';

export async function authRoutes(app: FastifyInstance) {
  // POST /api/v1/auth/register
  app.post('/register', async (request, reply) => {
    const parsed = registerSchema.safeParse(request.body);
    if (!parsed.success) {
      return errorResponse(reply, 'Validation error', 400, parsed.error.flatten());
    }

    const { name, email, password, slug: rawSlug } = parsed.data;

    // Check email uniqueness
    const existing = await prisma.tenant.findUnique({ where: { email } });
    if (existing) {
      return errorResponse(reply, 'This email is already registered', 409);
    }

    const slug = rawSlug || generateSlug(name);

    // Check slug uniqueness
    const slugExists = await prisma.tenant.findUnique({ where: { slug } });
    if (slugExists) {
      return errorResponse(reply, 'This slug is already taken', 409);
    }

    const passwordHash = await hashPassword(password);
    const apiKey = generateApiKey();
    const apiSecret = generateApiSecret();
    const apiSecretHash = await hashPassword(apiSecret);
    const webhookSecret = generateWebhookSecret();

    const tenant = await prisma.tenant.create({
      data: {
        name,
        slug,
        email,
        passwordHash,
        apiKey,
        apiSecretHash,
        webhookSecret,
      },
      select: {
        id: true,
        name: true,
        slug: true,
        email: true,
        apiKey: true,
        webhookSecret: true,
        createdAt: true,
      },
    });

    const tokens = generateTokens({ tenantId: tenant.id, email: tenant.email });

    return successResponse(reply, {
      tenant,
      apiSecret, // Only returned once at registration
      ...tokens,
    }, 201);
  });

  // POST /api/v1/auth/login
  app.post('/login', async (request, reply) => {
    const parsed = loginSchema.safeParse(request.body);
    if (!parsed.success) {
      return errorResponse(reply, 'Validation error', 400, parsed.error.flatten());
    }

    const { email, password } = parsed.data;

    const tenant = await prisma.tenant.findUnique({
      where: { email },
      select: {
        id: true,
        name: true,
        slug: true,
        email: true,
        passwordHash: true,
        isActive: true,
      },
    });

    if (!tenant || !tenant.isActive) {
      return errorResponse(reply, 'Invalid email or password', 401);
    }

    const valid = await verifyPassword(password, tenant.passwordHash);
    if (!valid) {
      return errorResponse(reply, 'Invalid email or password', 401);
    }

    const tokens = generateTokens({ tenantId: tenant.id, email: tenant.email });

    return successResponse(reply, {
      tenant: {
        id: tenant.id,
        name: tenant.name,
        slug: tenant.slug,
        email: tenant.email,
      },
      ...tokens,
    });
  });

  // GET /api/v1/auth/me
  app.get('/me', { preHandler: [authMiddleware] }, async (request, reply) => {
    const tenant = await prisma.tenant.findUnique({
      where: { id: request.tenantId! },
      select: {
        id: true,
        name: true,
        slug: true,
        email: true,
        apiKey: true,
        webhookUrl: true,
        domain: true,
        igAccountId: true,
        igPageId: true,
        plan: true,
        settings: true,
        isActive: true,
        createdAt: true,
      },
    });

    return successResponse(reply, tenant);
  });

  // POST /api/v1/auth/api-key/regenerate
  app.post('/api-key/regenerate', { preHandler: [authMiddleware] }, async (request, reply) => {
    const apiKey = generateApiKey();
    const apiSecret = generateApiSecret();
    const apiSecretHash = await hashPassword(apiSecret);

    await prisma.tenant.update({
      where: { id: request.tenantId! },
      data: { apiKey, apiSecretHash },
    });

    return successResponse(reply, { apiKey, apiSecret });
  });
}
