import { Injectable, NotFoundException } from "@nestjs/common";
import * as bcrypt from "bcryptjs";
import { PrismaService } from "../../infra/prisma/prisma.service";
import { BroadcastNotificationDto } from "./dto/broadcast-notification.dto";
import { CreateTenantDto } from "./dto/create-tenant.dto";
import { TenantStatus, UserRole } from "@prisma/client";

@Injectable()
export class SaaSAdminService {
  constructor(private readonly prisma: PrismaService) {}

  async findAllTenants() {
    const companies = await this.prisma.company.findMany({
      include: {
        users: {
          select: { id: true, name: true, email: true, role: true, active: true },
        },
      },
      orderBy: { createdAt: "desc" },
    });

    return companies.map((c) => ({
      id: c.id,
      legalName: c.legalName,
      tradeName: c.tradeName,
      document: c.document,
      email: c.email,
      phone: c.phone,
      status: c.status,
      plan: c.plan,
      monthlyFee: Number(c.monthlyFee),
      dueDay: c.dueDay,
      lastPaymentStatus: c.lastPaymentStatus,
      userCount: c.users.length,
      users: c.users,
      createdAt: c.createdAt.toISOString(),
      updatedAt: c.updatedAt.toISOString(),
    }));
  }

  async getSaaSFinancialSummary() {
    const companies = await this.prisma.company.findMany();

    const totalTenants = companies.length;
    const activeTenants = companies.filter((c) => c.status === TenantStatus.ACTIVE).length;
    const suspendedTenants = companies.filter((c) => c.status === TenantStatus.SUSPENDED).length;
    const trialTenants = companies.filter((c) => c.status === TenantStatus.TRIAL).length;

    const mrr = companies
      .filter((c) => c.status === TenantStatus.ACTIVE)
      .reduce((acc, c) => acc + Number(c.monthlyFee), 0);

    const arr = mrr * 12;

    const overdueRevenue = companies
      .filter((c) => c.lastPaymentStatus === "OVERDUE" || c.status === TenantStatus.SUSPENDED)
      .reduce((acc, c) => acc + Number(c.monthlyFee), 0);

    return {
      totalTenants,
      activeTenants,
      suspendedTenants,
      trialTenants,
      mrr,
      arr,
      overdueRevenue,
    };
  }

  async createTenant(dto: CreateTenantDto) {
    const company = await this.prisma.company.create({
      data: {
        legalName: dto.legalName,
        tradeName: dto.tradeName || dto.legalName,
        document: dto.document,
        email: dto.email,
        phone: dto.phone,
        status: dto.status || TenantStatus.ACTIVE,
        plan: dto.plan || "Pro Enterprise",
        monthlyFee: dto.monthlyFee ?? 499.0,
        dueDay: dto.dueDay ?? 10,
        lastPaymentStatus: "PAID",
      },
    });

    const rawPassword = dto.adminPassword && dto.adminPassword.trim().length > 0 ? dto.adminPassword : "admin123";
    const passwordHash = await bcrypt.hash(rawPassword, 10);

    const user = await this.prisma.user.create({
      data: {
        companyId: company.id,
        name: dto.adminName,
        email: dto.adminEmail,
        passwordHash,
        role: UserRole.OWNER,
        active: true,
      },
    });

    return {
      company,
      user,
    };
  }

  async toggleTenantStatus(id: string, status: TenantStatus) {
    const company = await this.prisma.company.findUnique({ where: { id } });
    if (!company) {
      throw new NotFoundException("Empresa não encontrada.");
    }

    const updated = await this.prisma.company.update({
      where: { id },
      data: { status },
    });

    return updated;
  }

  async updateTenantBilling(
    id: string,
    data: { monthlyFee?: number; dueDay?: number; lastPaymentStatus?: string }
  ) {
    const company = await this.prisma.company.findUnique({ where: { id } });
    if (!company) {
      throw new NotFoundException("Empresa não encontrada.");
    }

    const updated = await this.prisma.company.update({
      where: { id },
      data: {
        ...(data.monthlyFee !== undefined ? { monthlyFee: data.monthlyFee } : {}),
        ...(data.dueDay !== undefined ? { dueDay: data.dueDay } : {}),
        ...(data.lastPaymentStatus ? { lastPaymentStatus: data.lastPaymentStatus } : {}),
      },
    });

    return updated;
  }

  async createBroadcastNotification(dto: BroadcastNotificationDto) {
    const notification = await this.prisma.systemNotification.create({
      data: {
        companyId: dto.companyId || null,
        title: dto.title,
        message: dto.message,
        type: dto.type || "INFO",
        active: true,
        expiresAt: dto.expiresAt ? new Date(dto.expiresAt) : null,
      },
    });

    return notification;
  }

  async getActiveNotifications(companyId?: string) {
    const whereClause: any = { active: true };
    if (companyId && companyId !== "all" && companyId !== "default") {
      whereClause.OR = [{ companyId: null }, { companyId }];
    }

    const notifications = await this.prisma.systemNotification.findMany({
      where: whereClause,
      orderBy: { createdAt: "desc" },
    });

    return notifications;
  }

  async findSaaSAdmins() {
    return this.prisma.user.findMany({
      where: { role: UserRole.SUPERADMIN },
      select: {
        id: true,
        name: true,
        email: true,
        role: true,
        active: true,
        createdAt: true,
      },
      orderBy: { createdAt: "desc" },
    });
  }

  async createSaaSAdmin(data: { name: string; email: string }) {
    const company = await this.prisma.company.findFirst();
    if (!company) {
      throw new NotFoundException("Nenhuma empresa cadastrada no sistema.");
    }

    return this.prisma.user.create({
      data: {
        companyId: company.id,
        name: data.name,
        email: data.email,
        passwordHash: "$2b$10$mocked-hash",
        role: UserRole.SUPERADMIN,
        active: true,
      },
      select: {
        id: true,
        name: true,
        email: true,
        role: true,
        active: true,
        createdAt: true,
      },
    });
  }

  async deleteSaaSAdmin(id: string) {
    return this.prisma.user.delete({
      where: { id, role: UserRole.SUPERADMIN },
    });
  }

  async updateSaaSAdmin(id: string, data: { name?: string; email?: string; password?: string }) {
    return this.prisma.user.update({
      where: { id, role: UserRole.SUPERADMIN },
      data: {
        ...(data.name ? { name: data.name } : {}),
        ...(data.email ? { email: data.email } : {}),
        ...(data.password ? { passwordHash: `$2b$10$updated-${data.password}` } : {}),
      },
      select: {
        id: true,
        name: true,
        email: true,
        role: true,
        active: true,
        createdAt: true,
      },
    });
  }

  async resetProductionDatabase() {
    await this.prisma.serviceOrder.deleteMany({});
    await this.prisma.cashMovement.deleteMany({});
    await this.prisma.accountPayable.deleteMany({});
    await this.prisma.accountReceivable.deleteMany({});
    await this.prisma.rentalItem.deleteMany({});
    await this.prisma.rental.deleteMany({});
    await this.prisma.equipment.deleteMany({});
    await this.prisma.category.deleteMany({});
    await this.prisma.customer.deleteMany({});
    await this.prisma.supplier.deleteMany({});
    await this.prisma.systemNotification.deleteMany({});
    await this.prisma.auditLog.deleteMany({});
    await this.prisma.user.deleteMany({});
    await this.prisma.company.deleteMany({});

    const company = await this.prisma.company.create({
      data: {
        legalName: "BlackLoc Locacoes Industriais LTDA",
        tradeName: "BlackLoc ERP",
        document: "12345678000190",
        email: "admin@blackloc.com",
        phone: "(81) 3333-1000",
        status: TenantStatus.ACTIVE,
        plan: "Pro Enterprise",
        monthlyFee: 499.0,
        dueDay: 10,
        lastPaymentStatus: "PAID",
      },
    });

    const passwordHash = await bcrypt.hash("admin123", 10);

    await this.prisma.user.create({
      data: {
        companyId: company.id,
        name: "Administrador BlackLoc",
        email: "admin@blackloc.com",
        passwordHash,
        role: UserRole.OWNER,
        active: true,
      },
    });

    await this.prisma.user.create({
      data: {
        companyId: company.id,
        name: "Administrador Geral",
        email: "admin@rentx.local",
        passwordHash,
        role: UserRole.OWNER,
        active: true,
      },
    });

    await this.prisma.user.create({
      data: {
        companyId: company.id,
        name: "SuperAdmin Master",
        email: "superadmin@blackloc.com",
        passwordHash,
        role: UserRole.SUPERADMIN,
        active: true,
      },
    });

    await this.prisma.user.create({
      data: {
        companyId: company.id,
        name: "SuperAdmin RentX",
        email: "superadmin@rentx.local",
        passwordHash,
        role: UserRole.SUPERADMIN,
        active: true,
      },
    });

    return { message: "Banco de dados zerado e configurado para produção com sucesso!" };
  }
}
