module ProjectOperable
  extend ActiveSupport::Concern

  included do
    has_many :members, dependent: :destroy
    has_many :except_owner_members, -> { joins(:roles).where.not(roles: { name: 'Manager' }) }, class_name: 'Member'
    has_many :managers,             -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
    has_many :developers,           -> { joins(:roles).where(roles: { name: 'Developer' }) }, class_name: 'Member'
    has_many :reporters,            -> { joins(:roles).where(roles: { name: 'Reporter' }) }, class_name: 'Member'
    has_many :writable_members,     -> { joins(:roles).where.not(roles: {name: 'Reporter'}) }, class_name: 'Member'
    has_many :team_projects, dependent: :destroy
    has_many :teams, through: :team_projects, source: :team
  end

  def set_owner_permission(creator)
    return unless owner.is_a?(Organization)
    owner.build_permit_team_projects!(id)
    # 避免自己创建的项目，却无法拥有访问权，因为该用户所在团队暂未获得项目访问权
    return if creator.nil? || owner.is_owner?(creator.id)
    add_member!(creator.id, "Manager") if creator.is_a?(User)
  end

  def add_member!(user_id, role_name='Developer', is_apply_signature=false)
    # if self.owner.is_a?(Organization)
    #   case role_name
    #   when 'Manager'
    #     # 构建相应的团队
    #     team = self.owner.teams.admin.take
    #     if team.nil?
    #       team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
    #       gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
    #       team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
    #     end
    #
    #     # 设置项目在团队中的访问权限
    #     team_project = TeamProject.build(self.user_id, team.id, self.id)
    #     tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
    #
    #     # 新增对应的团队成员
    #     team_user = TeamUser.build(self.user_id, user_id, team.id)
    #     $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
    #
    #     # 确保组织成员中有该用户
    #     OrganizationUser.build(self.user_id, user_id)
    #   when 'Developer'
    #     # 构建相应的团队
    #     team = self.owner.teams.write.take
    #     if team.nil?
    #       team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
    #       gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
    #       team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
    #     end
    #
    #     # 设置项目在团队中的访问权限
    #     team_project = TeamProject.build(self.user_id, team.id, self.id)
    #     tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
    #
    #     # 新增对应的团队成员
    #     team_user = TeamUser.build(self.user_id, user_id, team.id)
    #     $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
    #
    #     # 确保组织成员中有该用户
    #     OrganizationUser.build(self.user_id, user_id)
    #   when 'Reporter'
    #     # 构建相应的团队
    #     team = self.owner.teams.read.take
    #     if team.nil?
    #       team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
    #       gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
    #       team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
    #     end
    #
    #     # 设置项目在团队中的访问权限
    #     team_project = TeamProject.build(self.user_id, team.id, self.id)
    #     tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
    #
    #     # 新增对应的团队成员
    #     team_user = TeamUser.build(self.user_id, user_id, team.id)
    #     $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
    #
    #     # 确保组织成员中有该用户
    #     OrganizationUser.build(self.user_id, user_id)
    #   end
    # end
    member = members.create!(user_id: user_id,  is_apply_signature: is_apply_signature)
    set_developer_role(member, role_name)
  end

  def remove_member!(user_id)
    member = members.find_by(user_id: user_id)
    member.destroy! if member && self.user_id != user_id
    team_user = TeamUser.find_by_id(member&.team_user_id)
    team_user.destroy! if team_user
  end

  # 安装bot后的权限
  def is_install_bot?(user)
    user.platform == "bot" && BotInstall.joins(:bot).where(bot: { uid: user.id }).where(store_id: self.id).exists?
  end

  def member?(user_id)
    if owner.is_a?(User)
      members.exists?(user_id: user_id) || is_install_bot?(User.find_by(id: user_id))
    elsif owner.is_a?(Organization)
      members.exists?(user_id: user_id) || team_projects.joins(team: :team_users).where(team_users: {user_id: user_id}).present?
    else
      false
    end
  end

  # 除了项目创建者本身
  def member(user_id)
    members.where.not("members.user_id = ? ", owner.id).find_by(user_id: user_id)
  end

  def change_member_role!(user_id, role)
    member = self.member(user_id)
    # 所有者为组织，并且该用户属于组织成员
    # if self.owner.is_a?(Organization) && member.team_user.present?
    #   case role&.name
    #   when 'Manager'
    #     # 构建相应的团队
    #     team = self.owner.teams.admin.take
    #     if team.nil?
    #       team = Team.build(self.user_id, 'admin', '管理员', '', 'admin', false, false)
    #       gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
    #       team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
    #     end
    #
    #     # 设置项目在团队中的访问权限
    #     team_project = TeamProject.build(self.user_id, team.id, self.id)
    #     tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
    #
    #     # 更改对应的团队成员
    #     team_user = member.team_user
    #     $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
    #     $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
    #     team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
    #
    #     # 确保组织成员中有该用户
    #     OrganizationUser.build(self.user_id, user_id)
    #   when 'Developer'
    #     # 构建相应的团队
    #     team = self.owner.teams.write.take
    #     if team.nil?
    #       team = Team.build(self.user_id, 'developer', '开发者', '', 'write', false, false)
    #       gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
    #       team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
    #     end
    #     # 设置项目在团队中的访问权限
    #     team_project = TeamProject.build(self.user_id, team.id, self.id)
    #     $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
    #
    #     # 更改对应的团队成员
    #     team_user = member.team_user
    #     $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
    #     $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
    #     team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
    #
    #     OrganizationUser.build(self.user_id, user_id)
    #   when 'Reporter'
    #     # 构建相应的团队
    #     team = self.owner.teams.read.take
    #     if team.nil?
    #       team = Team.build(self.user_id, 'reporter', '报告者', '', 'read', false, false)
    #       gteam = $gitea_client.post_orgs_teams_by_org(self.owner.login, {body: team.to_gitea_hash.to_json}) rescue nil
    #       team.update_attributes!({gtid: gteam["id"]}) unless gteam.nil?
    #     end
    #
    #     # 设置项目在团队中的访问权限
    #     team_project = TeamProject.build(self.user_id, team.id, self.id)
    #     tp_result = $gitea_client.put_teams_repos_by_id_org_repo(team.gtid, self.owner.login, self.identifier) rescue nil
    #
    #     # 更改对应的团队成员
    #     team_user = member.team_user
    #     $gitea_client.delete_teams_members_by_id_username(team_user.team.gtid, team_user.user&.login) rescue nil # 移除旧的
    #     $gitea_client.put_teams_members_by_id_username(team&.gtid, team_user.user&.login) rescue nil # 新增新的
    #     team_user.update_attributes!({team_id: team.id}) unless team.team_users.exists?(user_id: member.user_id)
    #
    #     # 确保组织成员中有该用户
    #     OrganizationUser.build(self.user_id, user_id)
    #   end
    # end
    member.member_roles.last.update_attributes!(role: role)
  end

  def owner?(user)
    if owner.is_a?(User)
      self.owner == user
    elsif owner.is_a?(Organization)
      owner.is_owner?(user.id)
    else
      false
    end
  end

  # 项目管理员(包含项目拥有者)，权限：仓库设置、仓库可读可写
  # 增加bot用户权限，已安装bot，当前bot用户即拥有权限，权限粒度待完善
  def manager?(user)
    if owner.is_a?(User)
      managers.exists?(user_id: user.id) || (user.platform == "bot" && BotInstall.joins(:bot).where(bot: { uid: user.id }).where(store_id: self.id).exists?)
    elsif owner.is_a?(Organization)
      managers.exists?(user_id: user.id) || owner.is_owner?(user.id) || (owner.is_admin?(user.id) && (teams.pluck(:id) & user.teams.pluck(:id)).size > 0) || (user.platform == "bot" && BotInstall.joins(:bot).where(bot: { uid: user.id }).where(store_id: self.id).exists?)
    else
      false
    end
  end

  # 项目开发者，可读可写权限
  # 增加bot用户权限，已安装当前bot用户对应的bot即拥有权限，权限粒度待完善
  def develper?(user)
    if owner.is_a?(User)
      developers.exists?(user_id: user.id) || (user.platform == "bot" && BotInstall.joins(:bot).where(bot: { uid: user.id }).where(store_id: self.id).exists?)
    elsif owner.is_a?(Organization)
      developers.exists?(user_id: user.id) || (owner.is_write?(user.id) && (teams.pluck(:id) & user.teams.pluck(:id)).size > 0) || (user.platform == "bot" && BotInstall.joins(:bot).where(bot: { uid: user.id }).where(store_id: self.id).exists?)
    else
      false
    end
  end

  # 报告者，只有可读权限
  def reporter?(user)
    if owner.is_a?(User)
      reporters.exists?(user_id: user.id)
    elsif owner.is_a?(Organization)
      reporters.exists?(user_id: user.id) || owner.is_only_read?(user.id)
    else
      false
    end
  end

  def operator?(user)
    user.admin? || (member?(user.id) && !reporter?(user))
  end

  def set_developer_role(member, role_name)
    role = Role.find_by(name: role_name)
    member.member_roles.create!(role: role)
  end

  def has_menu_permission(unit_type)
    self.project_units.where(unit_type: unit_type).exists?
  end

  def all_collaborators 
    member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager Developer Reporter)}).to_sql 
    team_user_sql = User.joins(teams: :team_projects).where(team_projects: {project_id: self.id}).to_sql
    return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct
  end

  def all_developers
    member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager Developer)}).to_sql 
    team_user_sql = User.joins(teams: :team_projects).where(teams: {authorize: %w(owner admin write)}, team_projects: {project_id: self.id}).to_sql
    return User.from("( #{ member_sql } UNION #{ team_user_sql } ) AS users").distinct
  end

  def all_managers 
    member_sql = User.joins(members: :roles).where(members: {project_id: self.id}, roles: {name: %w(Manager)}).to_sql 
    team_user_sql = User.joins(teams: :team_projects).where(teams: {authorize: %w(owner admin)},team_projects: {project_id: self.id}).to_sql 
    return User.from("( #{ member_sql} UNION #{ team_user_sql } ) AS users").distinct
  end
end
