import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { UserPermissionCondition } from './entities/user-permission-condition.entity';
import { UserPermission } from '../user-permissions/entities/user-permission.entity';
import { CreateUserPermissionConditionDto } from './dto/create-user-permission-condition.dto';
import { UpdateUserPermissionConditionDto } from './dto/update-user-permission-condition.dto';
import { ModuleEntity } from 'src/modules/entities/module.entity';

@Injectable()
export class UserPermissionConditionsService {
  constructor(
    @InjectRepository(UserPermissionCondition, 'scheme_dbs')
    private readonly conditionRepo: Repository<UserPermissionCondition>,

    @InjectRepository(UserPermission, 'scheme_dbs')
    private readonly permissionRepo: Repository<UserPermission>,

    @InjectRepository(ModuleEntity, 'scheme_dbs') // <-- add module repo
    private readonly moduleRepo: Repository<ModuleEntity>,
  ) {}

  async create(dto: CreateUserPermissionConditionDto) {
    const perm = await this.permissionRepo.findOne({
      where: { id: dto.user_permission_id },
    });
    if (!perm) throw new NotFoundException('UserPermission not found');
    const module = await this.moduleRepo.findOne({
      where: { id: dto.module_id },
    });
    if (!module) throw new NotFoundException('Module not found');
    const condition = this.conditionRepo.create({
      userPermission: perm,
      module: module, // <-- assign module
      condition_field: dto.condition_field,
      condition_value: dto.condition_value,
      logic: dto.logic,
    });

    return this.conditionRepo.save(condition);
  }

  async findAll() {
    const conditions = await this.conditionRepo.find({
      relations: [
        'userPermission',
        'userPermission.permission',
        'userPermission.user', // <-- include user
        'module',
      ],
    });

    return conditions.map((cond) => ({
      id: cond.id,
      module: cond.module
        ? {
            id: cond.module.id,
            name: cond.module.name,
            slug: cond.module.slug,
          }
        : null, // if no module assigned
      userPermission: cond.userPermission
        ? {
            id: cond.userPermission.id,
            permission: cond.userPermission.permission || null,
            user: cond.userPermission.user
              ? {
                  id: cond.userPermission.user.id,
                  name: cond.userPermission.user.firstName, // adjust based on your user entity
                  email: cond.userPermission.user.email,
                }
              : null,
          }
        : null,
      condition_field: cond.condition_field,
      condition_value: cond.condition_value,
      logic: cond.logic,
    }));
  }

  async findOne(id: number) {
    const cond = await this.conditionRepo.findOne({
      where: { id },
      relations: [
        'userPermission',
        'userPermission.permission',
        'userPermission.user', // <-- include user
        'module',
      ],
    });
    if (!cond) throw new NotFoundException('Condition not found');

    return {
      id: cond.id,
      module: cond.module
        ? { id: cond.module.id, name: cond.module.name, slug: cond.module.slug }
        : null,
      userPermission: cond.userPermission
        ? {
            id: cond.userPermission.id,
            permission: cond.userPermission.permission || null,
            user: cond.userPermission.user
              ? {
                  id: cond.userPermission.user.id,
                  name: cond.userPermission.user.firstName,
                  email: cond.userPermission.user.email,
                }
              : null,
          }
        : null,
      condition_field: cond.condition_field,
      condition_value: cond.condition_value,
      logic: cond.logic,
    };
  }

  async update(id: number, dto: UpdateUserPermissionConditionDto) {
    const condition = await this.conditionRepo.findOne({
      where: { id },
      relations: ['userPermission', 'module'], // fetch relations for update
    });
    if (!condition) throw new NotFoundException('Condition not found');

    // if module_id is being updated
    if (dto.module_id) {
      const module = await this.moduleRepo.findOne({
        where: { id: dto.module_id },
      });
      if (!module) throw new NotFoundException('Module not found');
      condition.module = module;
    }

    // if user_permission_id is being updated
    if (dto.user_permission_id) {
      const perm = await this.permissionRepo.findOne({
        where: { id: dto.user_permission_id },
      });
      if (!perm) throw new NotFoundException('UserPermission not found');
      condition.userPermission = perm;
    }

    // assign other fields safely
    if (dto.condition_field !== undefined)
      condition.condition_field = dto.condition_field;
    if (dto.condition_value !== undefined)
      condition.condition_value = dto.condition_value;
    if (dto.logic !== undefined) condition.logic = dto.logic;

    return this.conditionRepo.save(condition);
  }
  async remove(id: number) {
    const condition = await this.conditionRepo.findOne({
      where: { id },
      relations: ['userPermission', 'module'],
    });
    if (!condition) throw new NotFoundException('Condition not found');

    // remove the actual entity
    return this.conditionRepo.remove(condition);
  }

  // Get dynamic permissions for all users, grouped by module
  async getUserPermissionsByUser(userId: number) {
    // 1️⃣ Fetch all UserPermissions for the user, including conditions, module, and permission
    const userPerms = await this.permissionRepo.find({
      where: { user: { id: userId } },
      relations: ['user', 'permission', 'conditions', 'conditions.module'],
    });

    // 2️⃣ Prepare a module map to group permissions by module
    const moduleMap: Record<string, any> = {};

    userPerms.forEach((up) => {
      up.conditions.forEach((cond) => {
        // Use module slug or 'general' if no module assigned
        const moduleSlug = cond.module?.slug || 'general';

        if (!moduleMap[moduleSlug]) {
          moduleMap[moduleSlug] = {
            module: cond.module
              ? {
                  id: cond.module.id,
                  name: cond.module.name,
                  slug: cond.module.slug,
                }
              : null,
            permissions: [],
          };
        }

        moduleMap[moduleSlug].permissions.push({
          userPermissionId: up.id,
          permission: up.permission,
          user: up.user
            ? {
                id: up.user.id,
                name: up.user.firstName,
                email: up.user.email,
              }
            : null,
          condition_field: cond.condition_field,
          condition_value: cond.condition_value,
          logic: cond.logic,
        });
      });
    });

    // 3️⃣ Return grouped permissions as array
    return Object.values(moduleMap);
  }
}
