import { Controller, Post, Get, Body, Req, Param, UseGuards, ForbiddenException, NotFoundException, Logger } from '@nestjs/common';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { PrismaService } from '../../prisma/prisma.service';
import { SubscriptionEngineService } from './subscription-engine.service';
import { PLANS_CONFIG, SubscriptionPlanName } from './plans.config';
import { PesePayGateway } from '../payments/gateways/pesepay.gateway';

@Controller('api/subscription')
export class SubscriptionController {
  private readonly logger = new Logger(SubscriptionController.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly subscriptionEngine: SubscriptionEngineService,
  ) {}

  @Get('status')
  @UseGuards(JwtAuthGuard)
  async getStatus(@Req() req: any) {
    const businessId = req.user.id;
    const business = await this.prisma.business.findUnique({
      where: { id: businessId },
    });

    if (!business) {
      throw new NotFoundException('Business not found');
    }

    const planName = business.subscriptionPlan as SubscriptionPlanName;
    const planConfig = PLANS_CONFIG[planName] || PLANS_CONFIG.FREE_TRIAL;

    const productsCount = await this.prisma.product.count({
      where: { businessId, status: 'ACTIVE' },
    });

    const customersCount = await this.prisma.customer.count({
      where: { businessId },
    });

    return {
      plan: business.subscriptionPlan,
      status: business.subscriptionStatus,
      trialStart: business.trialStart,
      trialEnd: business.trialEnd,
      subscriptionStart: business.subscriptionStart,
      subscriptionEnd: business.subscriptionEnd,
      usage: {
        deliveries: {
          current: business.deliveriesCount,
          limit: planConfig.limits.deliveries,
        },
        customers: {
          current: customersCount,
          limit: planConfig.limits.customers,
        },
        products: {
          current: productsCount,
          limit: planConfig.limits.products,
        },
        apiRequests: {
          current: business.apiRequestsCount,
          limit: planConfig.limits.api_requests,
        },
      },
    };
  }

  @Post('initiate-payment')
  @UseGuards(JwtAuthGuard)
  async initiatePayment(
    @Req() req: any,
    @Body() body: { plan: string; cycle: 'monthly' | 'semi' | 'annual' },
  ) {
    const businessId = req.user.id;
    const { plan, cycle } = body;

    const upperPlan = plan.toUpperCase() as SubscriptionPlanName;
    const planConfig = PLANS_CONFIG[upperPlan];

    if (!planConfig || upperPlan === 'FREE_TRIAL') {
      throw new ForbiddenException('Invalid plan selected');
    }

    const business = await this.prisma.business.findUnique({
      where: { id: businessId },
    });

    if (!business) {
      throw new NotFoundException('Business not found');
    }

    // Determine amount based on plan and billing cycle
    let rate = 0;
    let months = 1;
    if (cycle === 'monthly') {
      rate = planConfig.pricing.monthly;
      months = 1;
    } else if (cycle === 'semi') {
      rate = planConfig.pricing.semi;
      months = 6;
    } else if (cycle === 'annual') {
      rate = planConfig.pricing.annual;
      months = 12;
    } else {
      throw new ForbiddenException('Invalid billing cycle');
    }

    const amount = rate * months;
    const reference = `SUB-${businessId}-${upperPlan}-${cycle}-${Date.now()}`;

    // Create pending subscription payment record
    const payment = await this.prisma.subscriptionPayment.create({
      data: {
        businessId,
        plan: upperPlan,
        billingCycle: cycle,
        amount,
        currency: 'USD',
        gateway: 'pesepay',
        paymentReference: reference,
        status: 'PENDING',
      },
    });

    // Initialize PesePay gateway using platform environment keys
    const pesepay = new PesePayGateway({
      pesepayMerchantKey: process.env.PESEPAY_INTEGRATION_KEY,
      pesepayEncryptionKey: process.env.PESEPAY_ENCRYPTION_KEY,
      isSandbox: process.env.PESEPAY_SANDBOX === 'true',
    });

    const callbackUrl = `${process.env.PUBLIC_URL || 'http://localhost:3001'}/webhooks/payments/pesepay`;
    const returnUrl = `${process.env.FRONTEND_URL || 'http://localhost:3000'}/dashboard/billing/confirm?reference=${reference}`;

    try {
      const linkResult = await pesepay.createPaymentLink(
        reference,
        amount,
        'USD',
        business.contactEmail,
        callbackUrl,
      );

      // Update payment record with links and gateway reference
      await this.prisma.subscriptionPayment.update({
        where: { id: payment.id },
        data: {
          paymentLink: linkResult.paymentLink,
          gatewayReference: linkResult.paymentReference,
        },
      });

      return {
        success: true,
        paymentLink: linkResult.paymentLink,
        reference,
      };
    } catch (err: any) {
      this.logger.error(`Failed to initiate PesePay subscription payment: ${err.message}`);
      throw new ForbiddenException(`Payment initiation failed: ${err.message}`);
    }
  }

  @Post('verify-payment')
  @UseGuards(JwtAuthGuard)
  async verifyPayment(@Req() req: any, @Body() body: { reference: string }) {
    const businessId = req.user.id;
    const { reference } = body;

    const payment = await this.prisma.subscriptionPayment.findUnique({
      where: { paymentReference: reference },
    });

    if (!payment || payment.businessId !== businessId) {
      throw new NotFoundException('Subscription payment not found');
    }

    if (payment.status === 'SUCCESS') {
      return { success: true, status: 'SUCCESS' };
    }

    // Call PesePay gateway to poll status
    const pesepay = new PesePayGateway({
      pesepayMerchantKey: process.env.PESEPAY_INTEGRATION_KEY,
      pesepayEncryptionKey: process.env.PESEPAY_ENCRYPTION_KEY,
      isSandbox: process.env.PESEPAY_SANDBOX === 'true',
    });

    try {
      const verification = await pesepay.verifyPayment(payment.gatewayReference || reference);
      
      if (verification && verification.status === 'SUCCESS') {
        await this.subscriptionEngine.confirmSubscription(reference, verification.gatewayReference || reference);
        return { success: true, status: 'SUCCESS' };
      } else if (verification && verification.status === 'FAILED') {
        await this.prisma.subscriptionPayment.update({
          where: { id: payment.id },
          data: { status: 'FAILED' },
        });
        return { success: false, status: 'FAILED' };
      }
    } catch (err) {
      this.logger.error(`Error verifying PesePay subscription status: ${err}`);
    }

    const updatedPayment = await this.prisma.subscriptionPayment.findUnique({
      where: { id: payment.id },
    });
    return { success: false, status: updatedPayment?.status || payment.status };
  }

  @Get('payment-status/:reference')
  @UseGuards(JwtAuthGuard)
  async getPaymentStatus(@Req() req: any, @Param('reference') reference: string) {
    const businessId = req.user.id;
    const payment = await this.prisma.subscriptionPayment.findUnique({
      where: { paymentReference: reference },
    });

    if (!payment || payment.businessId !== businessId) {
      throw new NotFoundException('Subscription payment not found');
    }

    if (payment.status === 'SUCCESS') {
      const business = await this.prisma.business.findUnique({
        where: { id: businessId },
        select: { subscriptionStatus: true, subscriptionPlan: true, onboardingStep: true, selectedPlan: true },
      });
      return {
        success: true,
        status: 'SUCCESS',
        business,
      };
    }

    // Attempt double-check with gateway if still PENDING
    if (payment.status === 'PENDING') {
      const pesepay = new PesePayGateway({
        pesepayMerchantKey: process.env.PESEPAY_INTEGRATION_KEY,
        pesepayEncryptionKey: process.env.PESEPAY_ENCRYPTION_KEY,
        isSandbox: process.env.PESEPAY_SANDBOX === 'true',
      });

      try {
        const verification = await pesepay.verifyPayment(payment.gatewayReference || reference);
        if (verification && verification.status === 'SUCCESS') {
          await this.subscriptionEngine.confirmSubscription(reference, verification.gatewayReference || reference);
          const updatedBusiness = await this.prisma.business.findUnique({
            where: { id: businessId },
            select: { subscriptionStatus: true, subscriptionPlan: true, onboardingStep: true, selectedPlan: true },
          });
          return {
            success: true,
            status: 'SUCCESS',
            business: updatedBusiness,
          };
        }
      } catch (err: any) {
        this.logger.warn(`Verification check warning for ${reference}: ${err.message}`);
      }
    }

    return {
      success: true,
      status: payment.status,
    };
  }

  @Post('activate-trial')
  @UseGuards(JwtAuthGuard)
  async activateTrial(@Req() req: any) {
    const businessId = req.user.id;
    const business = await this.prisma.business.findUnique({
      where: { id: businessId },
    });

    if (!business) {
      throw new NotFoundException('Business not found');
    }

    const now = new Date();

    // 1. If trial is already active, return it
    if (business.subscriptionStatus === 'TRIAL') {
      if (business.trialEnd && now < business.trialEnd) {
        return { success: true, message: 'Free trial is active', trialEnd: business.trialEnd };
      }
    }

    // 2. If unsubscribed and never used trial before, activate it now!
    if (business.subscriptionStatus === 'UNSUBSCRIBED' && !business.trialEnd) {
      const trialEnd = new Date();
      trialEnd.setDate(trialEnd.getDate() + 14);

      const updated = await this.prisma.business.update({
        where: { id: businessId },
        data: {
          subscriptionStatus: 'TRIAL',
          onboardingStep: 'ONBOARDING_COMPLETED',
          trialStart: now,
          trialEnd,
        },
      });

      return { success: true, message: 'Free trial activated', trialEnd: updated.trialEnd };
    }

    // If their trial has expired, they cannot reactivate it.
    throw new ForbiddenException('You are no longer eligible for a free trial.');
  }
}
