import { Injectable } from '@nestjs/common';
import { type Subscription as PrismaSubscription, type Plan as PrismaPlan } from '@prisma/client';
import { PrismaService } from '@modules/shared';
import { SubscriptionEntity, type SubscriptionProps } from '../../domain/entities/subscription.entity';
import { type ISubscriptionRepository } from '../../domain/repositories/subscription.repository';

type SubscriptionWithPlan = PrismaSubscription & { plan: PrismaPlan };

@Injectable()
export class PrismaSubscriptionRepository implements ISubscriptionRepository {
  constructor(private readonly prisma: PrismaService) {}

  async findById(id: string): Promise<SubscriptionEntity | null> {
    const subscription = await this.prisma.subscription.findUnique({
      where: { id },
      include: { plan: true },
    });
    return subscription ? this.toDomain(subscription) : null;
  }

  async findByUserId(userId: string): Promise<SubscriptionEntity | null> {
    const subscription = await this.prisma.subscription.findUnique({
      where: { userId },
      include: { plan: true },
    });
    return subscription ? this.toDomain(subscription) : null;
  }

  async save(entity: SubscriptionEntity): Promise<void> {
    await this.prisma.subscription.create({
      data: {
        id: entity.id,
        userId: entity.userId,
        planId: entity.planId,
        status: entity.status,
        currentPeriodStart: entity.currentPeriodStart,
        currentPeriodEnd: entity.currentPeriodEnd,
        cancelledAt: entity.cancelledAt,
      },
    });
  }

  async update(entity: SubscriptionEntity): Promise<void> {
    await this.prisma.subscription.update({
      where: { id: entity.id },
      data: {
        planId: entity.planId,
        status: entity.status,
        currentPeriodStart: entity.currentPeriodStart,
        currentPeriodEnd: entity.currentPeriodEnd,
        cancelledAt: entity.cancelledAt,
      },
    });
  }

  private toDomain(raw: SubscriptionWithPlan): SubscriptionEntity {
    const props: SubscriptionProps = {
      userId: raw.userId,
      planId: raw.planId,
      planTier: raw.plan.tier,
      status: raw.status,
      currentPeriodStart: raw.currentPeriodStart,
      currentPeriodEnd: raw.currentPeriodEnd,
      cancelledAt: raw.cancelledAt,
    };

    return new SubscriptionEntity(raw.id, props, raw.createdAt, raw.updatedAt);
  }
}
