
import dotenv from 'dotenv';
import mongoose from 'mongoose';
import Plan from '../models/Plan';
import Subscription from '../models/Subscription';
import { SubscriptionPeriod } from '../models/SubscriptionPeriod';

dotenv.config();

const fixSubscriptionPlans = async () => {
    try {
        const mongoUri = process.env.MONGODB_URI || 'mongodb://localhost:27017/clinic-management';
        await mongoose.connect(mongoUri);
        console.log('Connected to MongoDB');

        const plans = await Plan.find({});
        console.log(`Found ${plans.length} available plans`);

        // Update Free Trial plan features if exists
        const freePlan = plans.find(p => p.period === SubscriptionPeriod.FREELY);
        if (freePlan) {
            freePlan.features = [
                'Access to basic features',
                '48 hours trial period',
                'Limited appointments',
                'Email support'
            ];
            await freePlan.save();
            console.log('✓ Updated Free Trial plan features to 48 hours');
        }

        const subscriptions = await Subscription.find({});
        console.log(`Found ${subscriptions.length} total subscriptions`);

        let updatedCount = 0;

        for (const sub of subscriptions) {
            let matchedPlan = plans.find(p => p._id.toString() === sub.planId?.toString());
            let planInferred = false;

            // If no plan linked or invalid, try to infer it
            if (!matchedPlan || !sub.planId) {
                console.log(`Subscription ${sub._id} has invalid/missing planId. Attempting to fix...`);

                const duration = new Date(sub.endDate).getTime() - new Date(sub.startDate).getTime();
                const days = Math.round(duration / (1000 * 60 * 60 * 24));

                console.log(`Subscription duration (raw): ${days} days`);

                // Heuristic based on expected plan ranges (48h, 1 month, 6 months, annual).
                if (days <= 3) {
                    matchedPlan = plans.find(p => p.period === SubscriptionPeriod.FREELY);
                } else if (days <= 45) {
                    matchedPlan = plans.find(p => p.period === SubscriptionPeriod.MONTHLY);
                } else if (days <= 210) {
                    matchedPlan = plans.find(p => p.period === SubscriptionPeriod.SIX_MONTH);
                } else {
                    matchedPlan = plans.find(p => p.period === SubscriptionPeriod.ANNUAL);
                }

                if (matchedPlan) {
                    sub.planId = matchedPlan._id as any;
                    planInferred = true;
                } else {
                    console.warn(`Could not find a matching plan for duration ${days} days`);
                    continue; // Skip if we can't determine plan
                }
            }

            // Valid plan found (either existing or inferred)
            if (matchedPlan) {
                // Recalculate end date based on actual start date and plan period
                const correctEndDate = new Date(sub.startDate);

                switch (matchedPlan.period) {
                    case SubscriptionPeriod.FREELY:
                        correctEndDate.setDate(correctEndDate.getDate() + 2); // 48 hours
                        break;
                    case SubscriptionPeriod.MONTHLY:
                        correctEndDate.setMonth(correctEndDate.getMonth() + 1);
                        break;
                    case SubscriptionPeriod.SIX_MONTH:
                        correctEndDate.setMonth(correctEndDate.getMonth() + 6);
                        break;
                    case SubscriptionPeriod.ANNUAL:
                        correctEndDate.setFullYear(correctEndDate.getFullYear() + 1);
                        break;
                    default:
                        console.warn(`Unknown period ${matchedPlan.period} for subscription ${sub._id}`);
                }

                // Check if we need to update the end date (allow 1 minute tolerance)
                const timeDiff = Math.abs(correctEndDate.getTime() - new Date(sub.endDate).getTime());
                const needsDateUpdate = timeDiff > 60000;

                if (planInferred || needsDateUpdate) {
                    sub.endDate = correctEndDate;
                    await sub.save();

                    if (planInferred) {
                        console.log(`Fixed subscription ${sub._id}: Linked to "${matchedPlan.title}" and set duration to ${matchedPlan.period}`);
                    }
                    if (needsDateUpdate) {
                        console.log(`Updated subscription ${sub._id} end date: ${correctEndDate.toISOString()} (was ${new Date(sub.endDate).toISOString()})`);
                    }
                    updatedCount++;
                }
            }
        }

        console.log(`Repair complete. Updated ${updatedCount} subscriptions.`);
        process.exit(0);

    } catch (error) {
        console.error('Error fixing subscriptions:', error);
        process.exit(1);
    }
};

fixSubscriptionPlans();
