import { Request, Response } from 'express'; import { AppDataSource } from '../config/database'; import { Agent, AgentStatus } from '../entities/Agent'; import { Subscription, SubscriptionStatus } from '../entities/Subscription'; import { User } from '../entities/User'; import crypto from 'crypto'; const agentRepository = AppDataSource.getRepository(Agent); const subscriptionRepository = AppDataSource.getRepository(Subscription); const userRepository = AppDataSource.getRepository(User); export class SubscriptionController { /** * Create subscription/purchase agent access */ async createSubscription(req: Request, res: Response) { try { const { agentId } = req.params; const userId = (req as any).user.id; // Get agent const agent = await agentRepository.findOne({ where: { id: agentId, status: AgentStatus.APPROVED }, }); if (!agent) { return res.status(404).json({ error: 'Agent not found or not approved' }); } // Check if user already has active subscription const existing = await subscriptionRepository.findOne({ where: { userId, agentId, status: SubscriptionStatus.ACTIVE, }, }); if (existing) { return res.status(400).json({ error: 'You already have an active subscription to this agent', }); } // Calculate expiry const expiresAt = agent.isSubscription ? new Date( Date.now() + (agent.subscriptionDuration || 30) * 24 * 60 * 60 * 1000 ) : new Date('2099-12-31'); // One-time purchase = lifetime (or very long) // Create subscription (payment verification happens via webhook) const subscription = subscriptionRepository.create({ userId, agentId, expiresAt, status: SubscriptionStatus.ACTIVE, isPaymentVerified: false, // Will be verified via webhook }); const savedSubscription = await subscriptionRepository.save(subscription); // Generate payment reference (for Paystack) const paymentReference = `sub_${savedSubscription.id}_${Date.now()}`; savedSubscription.paymentReference = paymentReference; await subscriptionRepository.save(savedSubscription); res.status(201).json({ subscription: savedSubscription, payment: { reference: paymentReference, amount: agent.price, currency: 'NGN', // Adjust based on your setup }, }); } catch (error) { console.error('Create subscription error:', error); res.status(500).json({ error: 'Failed to create subscription' }); } } /** * Get user's subscriptions */ async getMySubscriptions(req: Request, res: Response) { try { const userId = (req as any).user.id; const subscriptions = await subscriptionRepository.find({ where: { userId }, relations: ['agent'], order: { createdAt: 'DESC' }, }); res.json(subscriptions); } catch (error) { console.error('Get subscriptions error:', error); res.status(500).json({ error: 'Failed to get subscriptions' }); } } /** * Cancel subscription */ async cancelSubscription(req: Request, res: Response) { try { const { id } = req.params; const userId = (req as any).user.id; const subscription = await subscriptionRepository.findOne({ where: { id, userId }, }); if (!subscription) { return res.status(404).json({ error: 'Subscription not found' }); } subscription.status = SubscriptionStatus.CANCELLED; await subscriptionRepository.save(subscription); res.json({ message: 'Subscription cancelled', subscription }); } catch (error) { console.error('Cancel subscription error:', error); res.status(500).json({ error: 'Failed to cancel subscription' }); } } /** * Verify payment via Paystack webhook */ async verifyPayment(req: Request, res: Response) { try { const secret = process.env.PAYSTACK_SECRET; if (!secret) { throw new Error('Paystack secret not configured'); } const hash = crypto .createHmac('sha512', secret) .update(JSON.stringify(req.body)) .digest('hex'); if (hash !== req.headers['x-paystack-signature']) { return res.status(401).json({ error: 'Invalid signature' }); } const event = req.body; if (event.event === 'charge.success') { const { reference, metadata } = event.data; // Find subscription by payment reference const subscription = await subscriptionRepository.findOne({ where: { paymentReference: reference }, }); if (subscription) { subscription.isPaymentVerified = true; subscription.status = SubscriptionStatus.ACTIVE; await subscriptionRepository.save(subscription); } } res.json({ received: true }); } catch (error) { console.error('Payment verification error:', error); res.status(500).json({ error: 'Payment verification failed' }); } } }