import {
  Injectable,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';

import { Tenant, TenantStatus } from '../entities/tenant.entity';
import { TenantPlan } from '../entities/tenant-plan.entity';
import { CreateTenantDto } from '../dto/create-tenant.dto';
import { UpdateTenantDto } from '../dto/update-tenant.dto';

@Injectable()
export class TenantsService {
  constructor(
    @InjectRepository(Tenant)
    private readonly tenantRepository: Repository<Tenant>,
    @InjectRepository(TenantPlan)
    private readonly planRepository: Repository<TenantPlan>,
  ) {}

  async create(dto: CreateTenantDto): Promise<Tenant> {
    // Verificar slug unico
    const existingSlug = await this.tenantRepository.findOne({
      where: { slug: dto.slug },
    });

    if (existingSlug) {
      throw new ConflictException('Slug already exists');
    }

    // Obtener plan por defecto si no se especifica
    let planId = dto.plan_id;
    if (!planId) {
      const freePlan = await this.planRepository.findOne({
        where: { code: 'starter' },
      });
      if (freePlan) {
        planId = freePlan.id;
      }
    }

    // Calcular fin de trial (14 dias)
    const trialEndsAt = new Date();
    trialEndsAt.setDate(trialEndsAt.getDate() + 14);

    const tenant = this.tenantRepository.create({
      ...dto,
      plan_id: planId,
      status: TenantStatus.TRIAL,
      trial_ends_at: trialEndsAt,
    });

    return this.tenantRepository.save(tenant);
  }

  async findById(id: string): Promise<Tenant | null> {
    return this.tenantRepository.findOne({
      where: { id },
      relations: ['plan'],
    });
  }

  async findBySlug(slug: string): Promise<Tenant | null> {
    return this.tenantRepository.findOne({
      where: { slug },
      relations: ['plan'],
    });
  }

  async findByIdOrFail(id: string): Promise<Tenant> {
    const tenant = await this.findById(id);
    if (!tenant) {
      throw new NotFoundException('Tenant not found');
    }
    return tenant;
  }

  async update(id: string, dto: UpdateTenantDto): Promise<Tenant> {
    const tenant = await this.findByIdOrFail(id);

    // Si cambia slug, verificar que no exista
    if (dto.slug && dto.slug !== tenant.slug) {
      const existingSlug = await this.tenantRepository.findOne({
        where: { slug: dto.slug },
      });
      if (existingSlug) {
        throw new ConflictException('Slug already exists');
      }
    }

    Object.assign(tenant, dto);
    return this.tenantRepository.save(tenant);
  }

  async remove(id: string): Promise<void> {
    const tenant = await this.findByIdOrFail(id);
    await this.tenantRepository.softDelete(id);
  }

  async getUsage(tenantId: string): Promise<any> {
    // TODO: Implementar cuando esten los modulos de CRM, Assets, Generation
    return {
      users: 0,
      clients: 0,
      brands: 0,
      generations_this_month: 0,
      storage_used_bytes: 0,
    };
  }

  async findAllPlans(): Promise<TenantPlan[]> {
    return this.planRepository.find({
      where: { is_active: true },
      order: { sort_order: 'ASC' },
    });
  }
}
