import {
  Injectable,
  ConflictException,
  NotFoundException,
  Logger,
} from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateTenantDto } from './dto/create-tenant.dto';
import { UpdateTenantDto } from './dto/update-tenant.dto';

@Injectable()
export class TenantsService {
  private readonly logger = new Logger(TenantsService.name);

  constructor(private readonly prisma: PrismaService) {}

  /**
   * Neuen Tenant (Mandant) anlegen.
   */
  async create(dto: CreateTenantDto) {
    // Slug-Duplikat pruefen
    const existing = await this.prisma.tenant.findUnique({
      where: { slug: dto.slug },
    });
    if (existing) {
      throw new ConflictException(`Tenant-Slug "${dto.slug}" bereits vergeben`);
    }

    const tenant = await this.prisma.tenant.create({
      data: {
        name: dto.name,
        slug: dto.slug,
        isActive: true,
        settings: (dto.settings ?? {}) as Prisma.InputJsonValue,
      },
    });

    this.logger.log(`Tenant erstellt: ${tenant.name} (${tenant.slug})`);

    // TODO: Tenant-Datenbank erstellen (tenant_{slug})
    // Das wird spaeter per Prisma Migrate automatisiert

    return tenant;
  }

  /**
   * Tenant nach ID finden.
   */
  async findById(id: string) {
    const tenant = await this.prisma.tenant.findUnique({
      where: { id },
      include: {
        _count: {
          select: { members: true },
        },
      },
    });

    if (!tenant) {
      throw new NotFoundException('Mandant nicht gefunden');
    }

    return {
      ...tenant,
      memberCount: tenant._count.members,
    };
  }

  /**
   * Alle Tenants auflisten.
   */
  async findAll(page = 1, limit = 20) {
    const skip = (page - 1) * limit;

    const [tenants, total] = await Promise.all([
      this.prisma.tenant.findMany({
        skip,
        take: limit,
        orderBy: { createdAt: 'desc' },
        include: {
          _count: {
            select: { members: true },
          },
        },
      }),
      this.prisma.tenant.count(),
    ]);

    return {
      data: tenants.map((t) => ({
        id: t.id,
        name: t.name,
        slug: t.slug,
        isActive: t.isActive,
        memberCount: t._count.members,
        createdAt: t.createdAt,
      })),
      meta: {
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
      },
    };
  }

  /**
   * Tenant aktualisieren.
   */
  async update(id: string, dto: UpdateTenantDto) {
    const tenant = await this.prisma.tenant.findUnique({ where: { id } });
    if (!tenant) {
      throw new NotFoundException('Mandant nicht gefunden');
    }

    return this.prisma.tenant.update({
      where: { id },
      data: {
        name: dto.name,
        isActive: dto.isActive,
        settings: dto.settings as Prisma.InputJsonValue,
      },
    });
  }

  /**
   * User einem Tenant zuweisen.
   */
  async addMember(tenantId: string, userId: string, role = 'MEMBER') {
    // Pruefen ob bereits Mitglied
    const existing = await this.prisma.tenantMembership.findUnique({
      where: {
        userId_tenantId: { userId, tenantId },
      },
    });

    if (existing) {
      throw new ConflictException('Benutzer ist bereits Mitglied');
    }

    return this.prisma.tenantMembership.create({
      data: {
        userId,
        tenantId,
        tenantRole: role,
        isActive: true,
      },
      include: {
        user: { select: { email: true, firstName: true, lastName: true } },
        tenant: { select: { name: true, slug: true } },
      },
    });
  }

  /**
   * User aus Tenant entfernen (Soft-Delete).
   */
  async removeMember(tenantId: string, userId: string) {
    return this.prisma.tenantMembership.update({
      where: {
        userId_tenantId: { userId, tenantId },
      },
      data: { isActive: false },
    });
  }
}
