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

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

  /**
   * 检查当前用户所属租户是否为超级租户
   */
  private async checkSuperTenant(currentTenantId?: number): Promise<void> {
    if (!currentTenantId) {
      throw new ForbiddenException('无法确定当前租户信息');
    }

    const currentTenant = await this.prisma.tenant.findUnique({
      where: { id: currentTenantId },
    });

    if (!currentTenant) {
      throw new ForbiddenException('当前租户不存在');
    }

    if (currentTenant.isSuper !== 1) {
      throw new ForbiddenException('只有超级租户才能操作租户管理');
    }
  }

  async create(
    createTenantDto: CreateTenantDto,
    creatorId?: number,
    currentTenantId?: number,
  ) {
    // 检查是否为超级租户
    await this.checkSuperTenant(currentTenantId);

    const { menuIds, ...tenantData } = createTenantDto;

    // 检查租户编码是否已存在
    const existingTenant = await this.prisma.tenant.findUnique({
      where: { code: tenantData.code },
    });
    if (existingTenant) {
      throw new BadRequestException('租户编码已存在');
    }

    // 如果提供了域名，检查域名是否已存在
    if (tenantData.domain) {
      const existingDomain = await this.prisma.tenant.findUnique({
        where: { domain: tenantData.domain },
      });
      if (existingDomain) {
        throw new BadRequestException('租户域名已存在');
      }
    }

    return this.prisma.tenant.create({
      data: {
        ...tenantData,
        creator: creatorId,
        menus:
          menuIds && menuIds.length > 0
            ? {
                create: menuIds.map((menuId) => ({
                  menuId,
                })),
              }
            : undefined,
      },
      include: {
        menus: {
          include: {
            menu: true,
          },
        },
      },
    });
  }

  async findAll(page: number = 1, pageSize: number = 10) {
    const skip = (page - 1) * pageSize;
    const [list, total] = await Promise.all([
      this.prisma.tenant.findMany({
        skip,
        take: pageSize,
        include: {
          menus: {
            include: {
              menu: true,
            },
          },
          _count: {
            select: {
              users: true,
              roles: true,
            },
          },
        },
        orderBy: {
          createTime: 'desc',
        },
      }),
      this.prisma.tenant.count(),
    ]);

    return {
      list,
      total,
      page,
      pageSize,
    };
  }

  async findOne(id: number) {
    const tenant = await this.prisma.tenant.findUnique({
      where: { id },
      include: {
        menus: {
          include: {
            menu: true,
          },
        },
        _count: {
          select: {
            users: true,
            roles: true,
          },
        },
      },
    });

    if (!tenant) {
      throw new NotFoundException('租户不存在');
    }

    return tenant;
  }

  async findByCode(code: string) {
    return this.prisma.tenant.findUnique({
      where: { code },
      include: {
        menus: {
          include: {
            menu: true,
          },
        },
      },
    });
  }

  async findByDomain(domain: string) {
    return this.prisma.tenant.findUnique({
      where: { domain },
      include: {
        menus: {
          include: {
            menu: true,
          },
        },
      },
    });
  }

  async update(
    id: number,
    updateTenantDto: UpdateTenantDto,
    modifierId?: number,
    currentTenantId?: number,
  ) {
    // 检查是否为超级租户
    await this.checkSuperTenant(currentTenantId);

    const { menuIds, ...tenantData } = updateTenantDto;

    // 检查租户是否存在
    await this.findOne(id);

    // 如果更新了code，检查是否冲突
    if (tenantData.code) {
      const existingTenant = await this.prisma.tenant.findFirst({
        where: {
          code: tenantData.code,
          id: { not: id },
        },
      });
      if (existingTenant) {
        throw new BadRequestException('租户编码已存在');
      }
    }

    // 如果更新了domain，检查是否冲突
    if (tenantData.domain) {
      const existingDomain = await this.prisma.tenant.findFirst({
        where: {
          domain: tenantData.domain,
          id: { not: id },
        },
      });
      if (existingDomain) {
        throw new BadRequestException('租户域名已存在');
      }
    }

    const data: any = {
      ...tenantData,
      modifier: modifierId,
    };

    // 如果提供了 menuIds，更新菜单关联
    if (menuIds !== undefined) {
      // 先删除所有现有菜单关联
      await this.prisma.tenantMenu.deleteMany({
        where: { tenantId: id },
      });

      // 创建新的菜单关联
      if (menuIds.length > 0) {
        data.menus = {
          create: menuIds.map((menuId) => ({
            menuId,
          })),
        };
      }
    }

    return this.prisma.tenant.update({
      where: { id },
      data,
      include: {
        menus: {
          include: {
            menu: true,
          },
        },
      },
    });
  }

  async remove(id: number, currentTenantId?: number) {
    // 检查是否为超级租户
    await this.checkSuperTenant(currentTenantId);

    // 检查租户是否存在
    await this.findOne(id);

    // 检查要删除的租户是否为超级租户
    const tenant = await this.prisma.tenant.findUnique({
      where: { id },
    });
    if (tenant?.isSuper === 1) {
      throw new BadRequestException('不能删除超级租户');
    }

    return this.prisma.tenant.delete({
      where: { id },
    });
  }

  /**
   * 获取租户的菜单树（根据租户分配的菜单）
   */
  async getTenantMenus(tenantId: number) {
    const tenant = await this.findOne(tenantId);

    if (!tenant) {
      throw new NotFoundException('租户不存在');
    }

    // 获取租户分配的所有菜单ID
    const tenantMenus = await this.prisma.tenantMenu.findMany({
      where: { tenantId },
      include: {
        menu: true,
      },
    });

    const menuIds = tenantMenus.map((tm) => tm.menuId);

    if (menuIds.length === 0) {
      return [];
    }

    // 获取所有菜单（包括父菜单，因为子菜单可能被分配）
    const allMenus = await this.prisma.menu.findMany({
      where: {
        OR: [
          { id: { in: menuIds } },
          { children: { some: { id: { in: menuIds } } } },
        ],
        validState: 1,
      },
      orderBy: {
        sort: 'asc',
      },
    });

    // 构建树形结构
    const buildTree = (menus: any[], parentId: number | null = null): any[] => {
      return menus
        .filter((menu) => menu.parentId === parentId)
        .map((menu) => ({
          ...menu,
          children: buildTree(menus, menu.id),
        }));
    };

    const menuTree = buildTree(allMenus);

    // 过滤：只保留被分配的菜单及其父菜单
    const filterMenus = (menus: any[]): any[] => {
      return menus
        .filter((menu) => {
          // 如果菜单被分配，保留
          if (menuIds.includes(menu.id)) {
            return true;
          }
          // 如果有子菜单被分配，保留
          if (menu.children && menu.children.length > 0) {
            const filteredChildren = filterMenus(menu.children);
            return filteredChildren.length > 0;
          }
          return false;
        })
        .map((menu) => {
          const filtered = { ...menu };
          if (menu.children && menu.children.length > 0) {
            filtered.children = filterMenus(menu.children);
          }
          return filtered;
        });
    };

    return filterMenus(menuTree);
  }
}
