import { ConflictException, Injectable, NotFoundException } from '@nestjs/common'
import { InjectModel } from '@nestjs/mongoose'
import { Model, Types } from 'mongoose'
import { Subscription, SubscriptionDocument } from '../schemas/subscription.schema.js'
import { TenantsService } from '../tenants/tenants.service.js'
import type { CreateSubscriptionDto } from './dto/create-subscription.dto.js'
import type { UpdateSubscriptionDto } from './dto/update-subscription.dto.js'

@Injectable()
export class SubscriptionsService {
  constructor(
    @InjectModel(Subscription.name) private readonly model: Model<SubscriptionDocument>,
    private readonly tenants: TenantsService,
  ) {}

  async create(dto: CreateSubscriptionDto): Promise<SubscriptionDocument> {
    const tenant = await this.tenants.findOneBySlug(dto.tenantSlug)
    const existing = await this.model.exists({ tenantId: tenant._id })
    if (existing) throw new ConflictException(`Tenant "${dto.tenantSlug}" already has a subscription`)

    return this.model.create({
      tenantId: tenant._id,
      plan: dto.plan ?? tenant.plan,
      status: dto.status ?? 'trialing',
      stripeCustomerId: dto.stripeCustomerId,
      stripeSubscriptionId: dto.stripeSubscriptionId,
    })
  }

  async findAllForTenants(tenantIds: Types.ObjectId[]): Promise<SubscriptionDocument[]> {
    return this.model.find({ tenantId: { $in: tenantIds } }).sort({ createdAt: -1 }).exec()
  }

  async findAll(): Promise<SubscriptionDocument[]> {
    return this.model.find().sort({ createdAt: -1 }).exec()
  }

  async findByTenantSlug(slug: string): Promise<SubscriptionDocument> {
    const tenant = await this.tenants.findOneBySlug(slug)
    const sub = await this.model.findOne({ tenantId: tenant._id }).exec()
    if (!sub) throw new NotFoundException(`No subscription for tenant "${slug}"`)
    return sub
  }

  async update(slug: string, dto: UpdateSubscriptionDto): Promise<SubscriptionDocument> {
    const tenant = await this.tenants.findOneBySlug(slug)
    const sub = await this.model
      .findOneAndUpdate({ tenantId: tenant._id }, dto, { new: true, runValidators: true })
      .exec()
    if (!sub) throw new NotFoundException(`No subscription for tenant "${slug}"`)
    return sub
  }
}
