import { Injectable } from '@nestjs/common';
import { Subscription, SubscriptionStatus } from '../entities/subscription.entity';
import { Plan } from '../entities/plan.entity';

@Injectable()
export class SubscriptionLifecycleService {
  createTrial(tenantId: string, plan: Plan): Subscription {
    const now = new Date();
    const sub = new Subscription();
    sub.tenantId = tenantId;
    sub.planId = plan.id;
    sub.status = 'trialing';
    sub.currentPeriodStart = now;
    sub.currentPeriodEnd = this.addDays(now, plan.trialDays);
    sub.trialEndsAt = sub.currentPeriodEnd;
    return sub;
  }

  activate(sub: Subscription): Subscription {
    sub.status = 'active';
    // Start full billing period from now
    const now = new Date();
    sub.currentPeriodStart = now;
    sub.currentPeriodEnd = this.addMonths(now, 1);
    sub.trialEndsAt = undefined;
    return sub;
  }

  renew(sub: Subscription): Subscription {
    sub.currentPeriodStart = sub.currentPeriodEnd;
    sub.currentPeriodEnd = this.addMonths(sub.currentPeriodEnd, 1);
    sub.status = 'active';
    // Apply scheduled downgrade if any
    if (sub.nextPlanId) {
      sub.planId = sub.nextPlanId;
      sub.nextPlanId = undefined;
    }
    return sub;
  }

  upgradeNow(sub: Subscription, newPlanId: string): Subscription {
    sub.planId = newPlanId;
    sub.nextPlanId = undefined;
    if (sub.status === 'trialing') {
      sub.status = 'active';
    }
    return sub;
  }

  scheduleDowngrade(sub: Subscription, newPlanId: string): Subscription {
    sub.nextPlanId = newPlanId;
    sub.cancelAtPeriodEnd = false;
    return sub;
  }

  cancel(sub: Subscription, immediate: boolean): Subscription {
    if (immediate) {
      sub.status = 'cancelled';
      sub.cancelledAt = new Date();
    } else {
      sub.cancelAtPeriodEnd = true;
    }
    return sub;
  }

  markPastDue(sub: Subscription): Subscription {
    sub.status = 'past_due';
    return sub;
  }

  expire(sub: Subscription): Subscription {
    sub.status = 'expired';
    sub.cancelledAt = new Date();
    return sub;
  }

  isActive(sub: Subscription): boolean {
    return sub.status === 'active' || sub.status === 'trialing';
  }

  private addDays(date: Date, days: number): Date {
    const d = new Date(date);
    d.setDate(d.getDate() + days);
    return d;
  }

  private addMonths(date: Date, months: number): Date {
    const d = new Date(date);
    d.setMonth(d.getMonth() + months);
    return d;
  }
}
