import { FastifyInstance } from 'fastify';
import { prisma } from '../../config/database.js';
import { authMiddleware } from '../../api/middleware/auth.middleware.js';
import { encrypt } from '../../utils/crypto.js';
import { successResponse, errorResponse } from '../../utils/helpers.js';
import { logger } from '../../utils/logger.js';
import {
  getInstagramAuthUrl,
  exchangeCodeForToken,
  getLongLivedToken,
  getUserPages,
  getInstagramAccountId,
  getIgProfile,
  subscribeToWebhooks,
} from './graph-api.service.js';

export async function instagramAuthRoutes(app: FastifyInstance) {
  // GET /api/v1/auth/instagram — Redirect to Instagram OAuth
  app.get('/instagram', { preHandler: [authMiddleware] }, async (request, reply) => {
    const state = request.tenantId!; // Use tenantId as state for simplicity
    const authUrl = getInstagramAuthUrl(state);
    return reply.redirect(authUrl);
  });

  // GET /api/v1/auth/instagram/callback — OAuth callback
  app.get('/instagram/callback', async (request, reply) => {
    const query = request.query as { code?: string; state?: string; error?: string };

    if (query.error) {
      logger.error({ error: query.error }, '[IG OAuth] Authorization denied');
      return errorResponse(reply, 'Instagram authorization was denied', 400);
    }

    if (!query.code || !query.state) {
      return errorResponse(reply, 'Missing code or state parameter', 400);
    }

    const tenantId = query.state;

    try {
      // 1. Exchange code for short-lived token
      const shortTokenData = await exchangeCodeForToken(query.code);
      logger.info('[IG OAuth] Got short-lived token');

      // 2. Exchange for long-lived token
      const longTokenData = await getLongLivedToken(shortTokenData.access_token);
      const longToken = longTokenData.access_token;
      const expiresIn = longTokenData.expires_in ?? 5184000; // 60 days default
      logger.info('[IG OAuth] Got long-lived token');

      // 3. Get user's Facebook Pages
      const pages = await getUserPages(longToken);
      if (pages.length === 0) {
        return errorResponse(reply, 'No Facebook Pages found. You need a Facebook Page linked to an Instagram Professional account.', 400);
      }

      // 4. Find Instagram Business Account from pages
      let igAccountId: string | null = null;
      let selectedPage: { id: string; name: string; access_token: string } | null = null;

      for (const page of pages) {
        const igId = await getInstagramAccountId(page.access_token, page.id);
        if (igId) {
          igAccountId = igId;
          selectedPage = page;
          break;
        }
      }

      if (!igAccountId || !selectedPage) {
        return errorResponse(reply, 'No Instagram Professional account found linked to your Facebook Pages.', 400);
      }

      // 5. Get IG profile info
      const profile = await getIgProfile(igAccountId, selectedPage.access_token);
      logger.info({ igUsername: profile.username, igAccountId }, '[IG OAuth] Instagram account found');

      // 6. Subscribe to webhooks
      await subscribeToWebhooks(selectedPage.id, selectedPage.access_token);

      // 7. Save to tenant
      const expiresAt = new Date(Date.now() + expiresIn * 1000);

      await prisma.tenant.update({
        where: { id: tenantId },
        data: {
          igAccountId,
          igAccessToken: encrypt(longToken),
          igPageId: selectedPage.id,
          igTokenExpiresAt: expiresAt,
        },
      });

      logger.info({ tenantId, igAccountId }, '[IG OAuth] Tenant connected successfully');

      // Redirect to dashboard with success
      return reply.redirect(`/dashboard?ig_connected=true&ig_username=${profile.username}`);
    } catch (err: any) {
      logger.error({ err: err.message }, '[IG OAuth] Error during callback');
      return errorResponse(reply, 'Failed to connect Instagram account', 500);
    }
  });

  // DELETE /api/v1/auth/instagram — Disconnect Instagram
  app.delete('/instagram', { preHandler: [authMiddleware] }, async (request, reply) => {
    await prisma.tenant.update({
      where: { id: request.tenantId! },
      data: {
        igAccountId: null,
        igAccessToken: null,
        igPageId: null,
        igTokenExpiresAt: null,
      },
    });

    return successResponse(reply, { disconnected: true });
  });
}
