class Organizations::OrganizationsController < Organizations::BaseController
  include AesCryptHelper
  before_action :require_login, except: [:index, :show, :recommend, :languages]
  # before_action :require_profile_completed, only: [:create]
  before_action :convert_image!, only: [:create, :update]
  before_action :load_organization, only: [:show, :update, :destroy, :update_news, :update_memo, :update_other, :languages]
  before_action :check_user_can_edit_org, only: [:update, :destroy]

  def index
    if current_user.logged?
      logged_organizations_sql = Organization.with_visibility(%w(common limited)).to_sql
      privacy_organizations_sql = Organization.with_visibility("privacy").joins(:organization_users).where(organization_users: {user_id: current_user.id}).to_sql
      @organizations = Organization.from("( #{ logged_organizations_sql } UNION #{ privacy_organizations_sql } ) AS users")
    else
      @organizations = Organization.with_visibility("common")
    end
    @organizations = @organizations.ransack(login_cont: params[:search]).result if params[:search].present?
    @organizations = @organizations.includes(:organization_extension).order("organization_extensions.#{sort_by} #{sort_direction}")
    @organizations = kaminari_paginate(@organizations)
  end

  def show
    @can_create_project = @organization.can_create_project?(current_user.id)
    @is_admin = can_edit_org?
    @is_member = @organization.is_member?(current_user.id)
    Cache::V2::OwnerCommonService.new(@organization.id).read
  end

  def create
    ActiveRecord::Base.transaction do
      tip_exception("无法使用以下关键词：#{organization_params[:name]}，请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
      Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate!
      @organization = Organizations::CreateService.call(current_user, organization_params)
      Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
      Cache::V2::OwnerCommonService.new(@organization.id).reset
    end
  rescue Exception => e
    uid_logger_error(e.message)
    tip_exception(e.message)
  end

  def update
    ActiveRecord::Base.transaction do
      Organizations::CreateForm.new(organization_params.merge(original_name: @organization.login)).validate!
      login = @organization.login
      @organization.login = organization_params[:name] if organization_params[:name].present?
      @organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
      @organization.save!
      sync_organization_extension!
      # 更改组织可见性为私有，则需将该组织下的所有仓库同步更改为私有仓库
      if organization_extension_params[:visibility] == "privacy"
        Project.where(user_id: @organization.id).where(is_public: true).each do |project|
          update_project_private(project)
        end
      end

      Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload)
      Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
      Cache::V2::OwnerCommonService.new(@organization.id).reset
    end
  rescue Exception => e
    uid_logger_error(e.message)
    tip_exception(e.message)
  end

  def update_news
    @organization.organization_extension.update_attributes!(news_banner_id: params[:news_banner_id],
                                                            news_title: params[:news_title],
                                                            news_url: params[:news_url],
                                                            news_content: params[:news_content])
    render_ok
  end

  def update_memo
    @organization.organization_extension.update_attributes!(memo: params[:memo])
    render_ok
  end

  def update_other
    @organization.organization_extension.update_attributes!(news_banner_id: params[:news_banner_id],
                                                            news_content: params[:news_content],
                                                            news_title: params[:news_title],
                                                            news_url: params[:news_url],
                                                            featured_content: params[:featured_content],
                                                            memo: params[:memo])
    render_ok
  end

  def languages
    projects = @organization.projects
    projects_count = @organization.projects.count

    languages_hash = Rails.cache.fetch("query/organizations/languages/#{@organization.id}", :expires_in => 1.days) do
      total_languages(projects)
    end

    languages_hash = languages_hash.sort { |x, y| y[1] <=> x[1] }
    sort_hash = Hash[*languages_hash.flatten]
    # Rails.logger.info "languages_hash=============#{sort_hash}"
    sort_hash= sort_hash.transform_values { |v|
      ActionController::Base.helpers.number_to_percentage((v / projects_count), precision: 1)
    }.select { |k, v| v != "0.0%" }
    render json: sort_hash
  end

  def destroy
    tip_exception("密码不正确") unless current_user.check_password?(password)
    ActiveRecord::Base.transaction do
      gitea_destroy = Gitea::Organization::DeleteService.call(current_user.gitea_token, @organization.login)
      if gitea_destroy[:status] == 204
        data_bank = @organization.attributes.to_json
        @organization.destroy!
        UserAction.create(action_id: @organization.id, action_type: "DestroyOrganization", user_id: current_user.id, :ip => request.remote_ip, data_bank: data_bank)
        render_ok
      elsif gitea_destroy[:status] == 500
        tip_exception("当组织内含有仓库时，无法删除此组织")
      else
        tip_exception("")
      end
    end
  rescue Exception => e
    uid_logger_error(e.message)
    tip_exception(e.message)
  end

  def recommend
    recommend = %W(xuos Huawei_Technology openatom_foundation pkecosystem TensorLayer)
    
    @organizations = Organization.includes(:organization_extension).where(organization_extensions: {recommend: true}).to_a.each_slice(group_size).to_a
  end

  private

  def organization_params
    params.permit(:name, :description, :website, :location,
                  :repo_admin_change_team_access, :visibility,
                  :max_repo_creation, :nickname)
  end

  def group_size 
    params.fetch(:group_size, 4).to_i
  end

  def password
    decrypt(params[:password]) rescue params[:password].to_s
  end

  def load_organization
    @organization = Organization.find_by(login: params[:id]) || Organization.find_by(id: params[:id])
    return render_not_found("组织不存在") if @organization.nil?
    return render_forbidden("没有查看组织的权限") if org_limited_condition || org_privacy_condition
  end

  def sort_by
    OrganizationExtension.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
  end

  def sort_direction
    %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
  end

  def set_max_repo_creation
    organization_params[:max_repo_creation].blank? ? -1 : organization_params[:max_repo_creation]
  end

  def organization_extension_params
    organization_params
    .except(:name, :nickname)
    .merge(max_repo_creation: set_max_repo_creation)
  end
  
  def sync_organization_extension!
    @organization.organization_extension.update_attributes!(organization_extension_params)
  end

  def update_project_private(project)
    project.update_attributes!(is_public: false)
    project.forked_projects.update_all(is_public: project.is_public)
    gitea_params = {
      private: true,
      default_branch: project.default_branch,
      website: project.website,
      name: project.identifier
    }
    gitea_repo = Gitea::Repository::UpdateService.call(@organization, project&.repository&.identifier, gitea_params)
    project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
    # 更新对应所属分类下的项目数量（私有）
    project.project_category.decrement!(:private_projects_count, 1) if project.project_category.present?
  end

  def total_languages(projects)
    languages_hash ={}
    projects.each do |p|
      result = Gitea::Repository::Languages::ListService.call(p.owner.login,
                                                              p.identifier, current_user&.gitea_token)
      next unless result[:status] === :success
      total_byte_size = result[:body].values.sum
      hash = result[:body].transform_values { |v|
        (v * 100.0 / total_byte_size).to_f
      }

      hash.each do |key,value|
        # Rails.logger.info "key=============#{key}:#{value}"
        if languages_hash.has_key?(key)
          languages_hash[key] = languages_hash[key] + value
        else
          languages_hash[key] = value
        end
      end
    end
    languages_hash
  end

end