import { DataSource } from 'typeorm';
import { UserEntityMt } from '../entities/user.entity.mt';
import { RoleServiceMt } from './role.service.mt';
import { ConcreteCrudService } from '@d8d/shared-crud';
import * as bcrypt from 'bcrypt';

const SALT_ROUNDS = 10;

export class UserServiceMt extends ConcreteCrudService<UserEntityMt> {
  private roleService: RoleServiceMt;

  constructor(dataSource: DataSource) {
    super(UserEntityMt, {
      userTracking: {
        createdByField: 'createdBy',
        updatedByField: 'updatedBy'
      },
      tenantOptions: {
        tenantIdField: 'tenantId',
        autoExtractFromContext: true
      }
    });
    this.roleService = new RoleServiceMt(dataSource);
  }

  /**
   * 创建用户，自动设置租户ID并加密密码
   */
  async createUser(userData: Partial<UserEntityMt>, tenantId?: number): Promise<UserEntityMt> {
    try {
      // 检查用户名是否已存在（租户内唯一）
      if (userData.username) {
        const existingUser = await this.getUserByUsername(userData.username, tenantId);
        if (existingUser) {
          throw new Error('用户名已存在');
        }
      }

      if (userData.password) {
        userData.password = await bcrypt.hash(userData.password, SALT_ROUNDS);
      }

      // 如果提供了租户ID，自动设置
      if (tenantId !== undefined) {
        userData.tenantId = tenantId;
      } else {
        // 如果没有提供租户ID，设置默认租户ID为1
        userData.tenantId = 1;
      }

      return await this.create(userData);
    } catch (error) {
      console.error('Error creating user:', error);
      throw new Error(`Failed to create user: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  /**
   * 根据用户名获取用户（自动添加租户过滤）
   */
  async getUserByUsername(username: string, tenantId?: number): Promise<UserEntityMt | null> {
    try {
      const where: any = { username };

      // 如果提供了租户ID，添加租户过滤
      if (tenantId !== undefined) {
        where.tenantId = tenantId;
      }

      return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
    } catch (error) {
      console.error('Error getting user by username:', error);
      throw new Error('Failed to get user by username');
    }
  }

  /**
   * 根据手机号获取用户（自动添加租户过滤）
   */
  async getUserByPhone(phone: string, tenantId?: number): Promise<UserEntityMt | null> {
    try {
      const where: any = { phone };

      // 如果提供了租户ID，添加租户过滤
      if (tenantId !== undefined) {
        where.tenantId = tenantId;
      }

      return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
    } catch (error) {
      console.error('Error getting user by phone:', error);
      throw new Error('Failed to get user by phone');
    }
  }

  /**
   * 根据账号（用户名或邮箱）获取用户（自动添加租户过滤）
   */
  async getUserByAccount(account: string, tenantId?: number): Promise<UserEntityMt | null> {
    try {
      const where: any = [
        { username: account },
        { email: account }
      ];

      // 如果提供了租户ID，添加租户过滤
      if (tenantId !== undefined) {
        where.forEach((condition: any) => {
          condition.tenantId = tenantId;
        });
      }

      return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
    } catch (error) {
      console.error('Error getting user by account:', error);
      throw new Error('Failed to get user by account');
    }
  }

  /**
   * 验证密码
   */
  async verifyPassword(user: UserEntityMt, password: string): Promise<boolean> {
    return password === user.password || bcrypt.compare(password, user.password);
  }

  /**
   * 为用户分配角色
   */
  async assignRoles(userId: number, roleIds: number[], tenantId?: number): Promise<UserEntityMt | null> {
    try {
      const user = await this.getById(userId, ['roles']);
      if (!user) return null;

      // 验证租户一致性
      if (tenantId !== undefined && user.tenantId !== tenantId) {
        throw new Error('无权操作该用户');
      }

      // 获取角色实体
      const roles = [];
      for (const roleId of roleIds) {
        const role = await this.roleService.getById(roleId);
        if (role) {
          // 验证角色租户一致性
          if (tenantId !== undefined && role.tenantId !== tenantId) {
            throw new Error(`无权操作角色ID: ${roleId}`);
          }
          roles.push(role);
        }
      }

      // 分配角色
      user.roles = roles;
      return await this.repository.save(user);
    } catch (error) {
      console.error('Error assigning roles:', error);
      throw new Error('Failed to assign roles');
    }
  }

  /**
   * 根据ID获取用户（自动添加租户过滤）
   */
  async getUserById(id: number, tenantId?: number): Promise<UserEntityMt | null> {
    try {
      const where: any = { id };

      // 如果提供了租户ID，添加租户过滤
      if (tenantId !== undefined) {
        where.tenantId = tenantId;
      }

      return await this.repository.findOne({ where, relations: ['roles', 'avatarFile'] });
    } catch (error) {
      console.error('Error getting user by id:', error);
      throw new Error('Failed to get user by id');
    }
  }

  /**
   * 更新用户信息（自动添加租户过滤）
   */
  async updateUser(id: number, userData: Partial<UserEntityMt>, tenantId?: number): Promise<UserEntityMt | null> {
    try {
      // 首先验证用户是否存在且属于指定租户
      const existingUser = await this.getUserById(id, tenantId);
      if (!existingUser) return null;

      // 如果更新密码，需要加密
      if (userData.password) {
        userData.password = await bcrypt.hash(userData.password, SALT_ROUNDS);
      }

      return await this.update(id, userData);
    } catch (error) {
      console.error('Error updating user:', error);
      throw new Error('Failed to update user');
    }
  }

  /**
   * 删除用户（自动添加租户过滤）
   */
  async deleteUser(id: number, tenantId?: number): Promise<boolean> {
    try {
      // 首先验证用户是否存在且属于指定租户
      const existingUser = await this.getUserById(id, tenantId);
      if (!existingUser) return false;

      return await this.delete(id);
    } catch (error) {
      console.error('Error deleting user:', error);
      throw new Error('Failed to delete user');
    }
  }

  /**
   * 获取所有用户（自动添加租户过滤）
   */
  async getUsers(tenantId?: number): Promise<UserEntityMt[]> {
    try {
      const where: any = {};

      // 如果提供了租户ID，添加租户过滤
      if (tenantId !== undefined) {
        where.tenantId = tenantId;
      }

      const [users] = await this.getList(1, 100, undefined, undefined, where, ['roles', 'avatarFile']);
      return users;
    } catch (error) {
      console.error('Error getting users:', error);
      throw new Error(`Failed to get users: ${error instanceof Error ? error.message : String(error)}`);
    }
  }
}