import Plan from '../models/Plan';
import { seedPlansData } from '../scripts/seedData/seedPlansData';

export class PlanService {
  private buildSeedKey(title: string, period: string): string {
    return `${title.trim().toLowerCase()}::${period.trim().toLowerCase()}`;
  }

  /**
   * Get all plans
   */
  async getAllPlans() {
    const plans = await Plan.find({}).sort({ price: 1, createdAt: 1 });
    return plans;
  }

  /**
   * Get plan by ID
   */
  async getPlanById(planId: string) {
    if (!planId) {
      throw new Error('Plan ID is required');
    }

    const plan = await Plan.findById(planId);
    if (!plan) {
      throw new Error('Plan not found');
    }

    return plan;
  }

  /**
   * Create a new plan
   */
  async createPlan(planData: any) {
    if (!planData.title || planData.price === undefined || planData.price === null) {
      throw new Error('Plan title and price are required');
    }

    const plan = new Plan(planData);
    await plan.save();

    return plan;
  }

  /**
   * Update plan
   */
  async updatePlan(planId: string, planData: any) {
    if (!planId) {
      throw new Error('Plan ID is required');
    }

    const plan = await Plan.findByIdAndUpdate(planId, planData, { new: true });
    if (!plan) {
      throw new Error('Plan not found');
    }

    return plan;
  }

  /**
   * Delete plan
   */
  async deletePlan(planId: string) {
    if (!planId) {
      throw new Error('Plan ID is required');
    }

    const plan = await Plan.findByIdAndDelete(planId);
    if (!plan) {
      throw new Error('Plan not found');
    }

    return plan;
  }

  /**
   * Reset plans based on seed plans data.
   * Existing plans that match by title+period are updated in-place
   * so references keep working where possible.
   */
  async resetPlansFromSeed() {
    const existingPlans = await Plan.find({});
    const existingByKey = new Map(
      existingPlans.map((plan) => [
        this.buildSeedKey(plan.title, plan.period),
        plan,
      ])
    );
    const seedKeys = new Set(seedPlansData.map((plan) => this.buildSeedKey(plan.title, plan.period)));

    let updatedCount = 0;
    let createdCount = 0;

    for (const seedPlan of seedPlansData) {
      const key = this.buildSeedKey(seedPlan.title, seedPlan.period);
      const existing = existingByKey.get(key);

      if (existing) {
        existing.title = seedPlan.title;
        existing.price = seedPlan.price;
        existing.period = seedPlan.period;
        existing.features = [...seedPlan.features];
        await existing.save();
        updatedCount += 1;
        continue;
      }

      await Plan.create(seedPlan);
      createdCount += 1;
    }

    const plansToDelete = existingPlans.filter((plan) => !seedKeys.has(this.buildSeedKey(plan.title, plan.period)));

    let deletedCount = 0;
    if (plansToDelete.length > 0) {
      const deleteIds = plansToDelete.map((plan) => plan._id);
      const result = await Plan.deleteMany({ _id: { $in: deleteIds } });
      deletedCount = result.deletedCount || 0;
    }

    const plans = await Plan.find({}).sort({ price: 1, createdAt: 1 });
    return {
      plans,
      summary: {
        updatedCount,
        createdCount,
        deletedCount,
        totalCount: plans.length,
      },
    };
  }
}

export default new PlanService();
