import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';
import { prisma } from '@shieldai/db';
import { RemovalStatus, Severity, AlertCategory, EntityTypes } from '@shieldai/types';
import type { RemovalStatus as PrismaRemovalStatus } from '@shieldai/db';
import {
  removeBrokersService,
  removeBrokersScheduler,
  brokerAlertPipeline,
  type PersonalInfo,
} from '@shieldai/removebrokers';
import { AuthRequest } from '../middleware/auth.middleware';

const REMOVAL_REQUEST_LIMITS: Record<string, number> = {
  basic: 5,
  plus: 20,
  premium: 999,
};

async function getSubscription(
  request: FastifyRequest,
  reply: FastifyReply,
): Promise<{ subscriptionId: string; tier: string } | null> {
  const authReq = request as AuthRequest;
  const userId = authReq.user?.id;

  if (!userId) {
    await reply.code(401).send({ error: 'User not authenticated' });
    return null;
  }

  const subscription = await prisma.subscription.findFirst({
    where: { userId, status: 'active' },
    select: { id: true, tier: true },
  });

  if (!subscription) {
    await reply.code(402).send({
      error: 'Subscription required',
      message: 'An active subscription is required for data broker removal',
    });
    return null;
  }

  return { subscriptionId: subscription.id, tier: subscription.tier };
}

export async function removebrokersRoutes(fastify: FastifyInstance) {
  // GET /removebrokers/brokers - List available data brokers
  fastify.get('/brokers', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as AuthRequest;
    if (!authReq.user?.id) {
      return reply.code(401).send({ error: 'User not authenticated' });
    }

    const query = request.query as { category?: string };
    let brokers = await removeBrokersService.getAvailableBrokers();

    if (query.category) {
      brokers = brokers.filter((b) => b.category === query.category);
    }

    return reply.send({
      brokers: brokers.map((b) => ({
        id: b.id,
        name: b.name,
        domain: b.domain,
        category: b.category,
        removalMethod: b.removalMethod,
        requiresAccount: b.requiresAccount,
        requiresVerification: b.requiresVerification,
        estimatedDays: b.estimatedDays,
        removalUrl: b.removalUrl,
      })),
    });
  });

  // GET /removebrokers/status - Get removal request status for user
  fastify.get('/status', async (request: FastifyRequest, reply: FastifyReply) => {
    const sub = await getSubscription(request, reply);
    if (!sub) return;

    try {
      const status = await removeBrokersService.getRemovalStatus(sub.subscriptionId);

      const total = status.length;
      const pending = status.filter((s) => s.status === RemovalStatus.PENDING).length;
      const submitted = status.filter((s) => s.status === RemovalStatus.SUBMITTED).length;
      const completed = status.filter((s) => s.status === RemovalStatus.COMPLETED).length;
      const failed = status.filter((s) => s.status === RemovalStatus.FAILED).length;

      const limit = REMOVAL_REQUEST_LIMITS[sub.tier] ?? 5;
      const remaining = Math.max(0, limit - total);

      return reply.send({
        stats: { total, pending, submitted, completed, failed },
        limit,
        remaining,
        tier: sub.tier,
        requests: status,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to fetch status';
      return reply.code(500).send({ error: message });
    }
  });

  // POST /removebrokers/scan - Scan for personal listings across brokers
  fastify.post('/scan', async (request: FastifyRequest, reply: FastifyReply) => {
    const sub = await getSubscription(request, reply);
    if (!sub) return;

    const body = request.body as { fullName?: string; email?: string; phone?: string; address?: string };

    if (!body.fullName) {
      return reply.code(400).send({
        error: 'Invalid request',
        message: 'fullName is required for scanning',
      });
    }

    try {
      const user = await prisma.user.findUnique({
        where: { id: (request as AuthRequest).user!.id },
      });

      const personalInfo: PersonalInfo = {
        fullName: body.fullName,
        email: body.email || user?.email,
        phone: body.phone,
        address: body.address
          ? { street: body.address }
          : undefined,
      };

      const results = await removeBrokersService.scanForListings(
        sub.subscriptionId,
        personalInfo,
      );

      const found = results.filter((r) => r.found);

      for (const listing of found) {
        try {
          await brokerAlertPipeline.sendListingFoundAlert({
            userId: (request as AuthRequest).user!.id,
            brokerName: listing.brokerName,
            brokerId: listing.brokerId,
            category: AlertCategory.INFO_BROKER_LISTING,
            severity: Severity.MEDIUM,
            title: `Personal listing found on ${listing.brokerName}`,
            description: `Your personal information was found on ${listing.brokerName} (${listing.brokerId}). Consider submitting a removal request.`,
            entities: [
               { type: EntityTypes.USER_ID, value: (request as AuthRequest).user!.id },
             ],
            metadata: { url: listing.url },
          });
        } catch {
          // Alert failure is non-critical
        }
      }

      return reply.send({
        brokersScanned: results.length,
        listingsFound: found.length,
        results,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Scan failed';
      return reply.code(500).send({ error: message });
    }
  });

  // POST /removebrokers/request - Create a new removal request
  fastify.post('/request', async (request: FastifyRequest, reply: FastifyReply) => {
    const sub = await getSubscription(request, reply);
    if (!sub) return;

    const body = request.body as {
      brokerId: string;
      fullName: string;
      email?: string;
      phone?: string;
      address?: {
        street?: string;
        city?: string;
        state?: string;
        zip?: string;
      };
      dob?: string;
      notes?: string;
    };

    if (!body.brokerId) {
      return reply.code(400).send({
        error: 'Invalid request',
        message: 'brokerId is required',
      });
    }

    if (!body.fullName) {
      return reply.code(400).send({
        error: 'Invalid request',
        message: 'fullName is required',
      });
    }

    const limit = REMOVAL_REQUEST_LIMITS[sub.tier] ?? 5;
    const currentCount = await prisma.removalRequest.count({
      where: { subscriptionId: sub.subscriptionId },
    });

    if (currentCount >= limit) {
      return reply.code(400).send({
        error: 'Request limit reached',
        message: `You have reached the maximum of ${limit} removal requests for your ${sub.tier} tier.`,
        currentCount,
        limit,
        upgradeTo: 'plus',
      });
    }

    try {
      const personalInfo: PersonalInfo = {
        fullName: body.fullName,
        email: body.email,
        phone: body.phone,
        address: body.address,
        dob: body.dob,
      };

      const req = await removeBrokersService.createRemovalRequest(
        sub.subscriptionId,
        body.brokerId,
        personalInfo,
        body.notes,
      );

      return reply.code(201).send({
        request: {
          id: req.id,
          brokerId: req.brokerId,
          status: req.status,
          method: req.method,
          createdAt: req.createdAt,
        },
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to create removal request';
      return reply.code(422).send({ error: message });
    }
  });

  // GET /removebrokers/request/:id - Get specific removal request
  fastify.get('/request/:id', async (request: FastifyRequest, reply: FastifyReply) => {
    const sub = await getSubscription(request, reply);
    if (!sub) return;

    const id = (request.params as { id: string }).id;

    try {
      const req = await prisma.removalRequest.findFirst({
        where: { id, subscriptionId: sub.subscriptionId },
        include: { broker: true },
      });

      if (!req) {
        return reply.code(404).send({ error: 'Removal request not found' });
      }

      return reply.send({
        request: {
          id: req.id,
          brokerId: req.brokerId,
          brokerName: req.broker?.name || null,
          status: req.status,
          method: req.method,
          attempts: req.attempts,
          submittedAt: req.submittedAt,
          completedAt: req.completedAt,
          error: req.error,
          notes: req.notes,
          createdAt: req.createdAt,
          updatedAt: req.updatedAt,
        },
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to fetch request';
      return reply.code(500).send({ error: message });
    }
  });

  // DELETE /removebrokers/request/:id - Cancel a removal request
  fastify.delete('/request/:id', async (request: FastifyRequest, reply: FastifyReply) => {
    const sub = await getSubscription(request, reply);
    if (!sub) return;

    const id = (request.params as { id: string }).id;

    try {
      const req = await prisma.removalRequest.findFirst({
        where: { id, subscriptionId: sub.subscriptionId },
      });

      if (!req) {
        return reply.code(404).send({ error: 'Removal request not found' });
      }

      if (req.status === RemovalStatus.COMPLETED) {
        return reply.code(400).send({
          error: 'Cannot cancel',
          message: 'Cannot cancel a completed removal request',
        });
      }

      await prisma.removalRequest.update({
        where: { id },
        data: { status: RemovalStatus.CANCELLED as PrismaRemovalStatus },
      });

      return reply.send({
        request: {
          id: req.id,
          status: RemovalStatus.CANCELLED,
        },
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Failed to cancel request';
      return reply.code(500).send({ error: message });
    }
  });

  // POST /removebrokers/process - Trigger processing of pending removals (admin)
  fastify.post('/process', async (request: FastifyRequest, reply: FastifyReply) => {
    const authReq = request as AuthRequest;
    if (!authReq.user?.id) {
      return reply.code(401).send({ error: 'User not authenticated' });
    }

    if (authReq.user.role !== 'support') {
      return reply.code(403).send({ error: 'Support access required' });
    }

    try {
      const results = await removeBrokersService.processPendingRequests();

      return reply.send({
        processed: results.length,
        results,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Processing failed';
      return reply.code(500).send({ error: message });
    }
  });

  // POST /removebrokers/verify/:id - Manually verify a removal
  fastify.post('/verify/:id', async (request: FastifyRequest, reply: FastifyReply) => {
    const sub = await getSubscription(request, reply);
    if (!sub) return;

    const id = (request.params as { id: string }).id;

    try {
      const req = await prisma.removalRequest.findFirst({
        where: { id, subscriptionId: sub.subscriptionId },
      });

      if (!req) {
        return reply.code(404).send({ error: 'Removal request not found' });
      }

      const result = await removeBrokersService.verifyRemoval(id);

      return reply.send({
        requestId: id,
        ...result,
      });
    } catch (error) {
      const message = error instanceof Error ? error.message : 'Verification failed';
      return reply.code(500).send({ error: message });
    }
  });
}
