class ProjectsController < ApplicationController
  load_and_authorize_resource
  before_action :set_project, only: %i[show edit update destroy master_sections project_deletion_popup assistant generate_assistant assistant_status reset_assistant]

  def assistant; end

  def reset_assistant
    @project.update!(index_name: nil)
    AssistantConversation.where(raggable: @project).update!(outdated: true)
    redirect_to assistant_project_path(@project), notice: "Assistant has been reset"
  end

  def assistant_v2
    return redirect_to assistant_project_path(@project) if @project.index_name.nil?

    @conversations = AssistantConversation.where(raggable: @project, user: current_user).order(:created_at).reverse_order
    @conversation = if @conversations.empty?
                      AssistantConversation.create!(raggable: @project, user: current_user)
                    else
                      params[:conversation_id] ? AssistantConversation.find(params[:conversation_id]) : @conversations.first
                    end
    gon.conversationId = @conversation.id
  end

  def generate_assistant
    @task = SystemTask.where(task_type: "GenerateAssistantV2", status: "running")
                      .where("metadata @> ?",
                             { project_id: @project.id }.to_json).last

    if @task.nil?
      status = SystemTask.where(task_class: "LLM", running: true).count.positive? ? "queued" : "running"
      running = status == "running"
      @task = SystemTask.create(
        task_type: "GenerateAssistantV2",
        task_class: "LLM",
        user_id: current_user.id,
        running:,
        status:,
        metadata: { raggable_type: "Project", project_id: @project.id }
      )
      ExecuteGenerateAssistantJob.perform_later(@task.id, current_user.id) if running
    end
    redirect_to assistant_status_project_path(@project, task_id: @task.id),
                notice: "Generating assistant. The process takes time, please be patient."
  end

  def assistant_status
    @task = SystemTask.find(params[:task_id])
  end

  def search
    query = params[:q]

    return if query.blank?

    # If Sprint Admin user then show all
    if current_user.role == "admin"
      projects = Project.where("title ilike ?", "%#{query}%")
      respondent_categories = RespondentCategory.where("name ilike ?", "%#{query}%")
      respondents = Respondent
                    .joins(:respondent_category)
                    .joins("INNER JOIN projects ON projects.id = respondent_categories.project_id")
                    .where("respondents.first_name ILIKE ?", "%#{query}%")
                    .pluck("respondents.id, respondents.first_name, respondents.respondent_category_id, projects.id")
    else
      projects = Project.where(organization: current_user.organization).where("title ilike ?", "%#{query}%")
      respondent_categories = RespondentCategory.joins(:project)
                                                .where("projects.organization_id = ?", current_user.organization.id)
                                                .where("name ilike ?", "%#{query}%")
      respondents = Respondent
                    .joins(:respondent_category)
                    .joins("INNER JOIN projects ON projects.id = respondent_categories.project_id")
                    .where("projects.organization_id = ?", current_user.organization.id)
                    .where("respondents.first_name ILIKE ?", "%#{query}%")
                    .pluck("respondents.id, respondents.first_name, respondents.respondent_category_id, projects.id")
    end

    results = {}

    results["projects"] = { heading: "Projects", data: projects } unless projects.empty?

    results["respondentCategories"] = { heading: "Sub-Projects", data: respondent_categories } unless respondent_categories.empty?

    results["respondents"] = { heading: "Respondents", data: respondents } unless respondents.empty?

    render json: { status: :ok, results: }
  end

  def project_deletion_popup
    gon.project = @project
  end

  # GET /projects or /projects.json
  def index
    @sample_project = Project.where(id: 113).first # Replace ID with sample project ID
    # Determine the base query for projects based on organization
    base_query = if current_user.admin?
                   Project.all
                 else
                   Project.where(organization: current_user.organization)
                 end

    # Adjust the base query based on the presence of the sample project
    @projects = if @sample_project
                  base_query.where.not(id: @sample_project.id)
                else
                  base_query
                end.order(created_at: :desc)

    gon.projects = @projects.as_json(methods: %i[image_url random_sprint_color])
    gon.brands = @projects.pluck(:brand).compact.reject(&:blank?).uniq
    gon.clients = @projects.pluck(:client).compact.reject(&:blank?).uniq
    gon.categories = @projects.pluck(:category).compact.reject(&:blank?).uniq
    gon.organizations = Organization.where(id: @projects.pluck(:organization_id).uniq)
    gon.is_admin = current_user.admin?
  end

  def master_sections
    @master_sections = @project.master_sections
  end

  # GET /projects/1 or /projects/1.json
  def show; end

  # GET /projects/new
  def new
    @project = Project.new
  end

  # GET /projects/1/edit
  def edit; end

  # POST /projects or /projects.json
  def create
    @project = Project.new(project_params)
    @project.organization = current_user.organization

    respond_to do |format|
      if @project.save
        format.html { redirect_to projects_path, notice: "Project was successfully created." }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /projects/1 or /projects/1.json
  def update
    respond_to do |format|
      if @project.update(project_params)
        format.html { redirect_to project_url(@project), notice: "Project was successfully updated." }
        format.json { render :show, status: :ok, location: @project }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /projects/1 or /projects/1.json
  def destroy
    @project.destroy

    flash[:notice] = "Project successfully deleted."
    render json: { status: :ok }

    # respond_to do |format|
    #   format.html { redirect_to projects_url, notice: "Project was successfully deleted." }
    #   format.json { head :no_content }
    # end
  end

  private

  # Use callbacks to share common setup or constraints between actions.
  def set_project
    @project = Project.find(params[:id])
  end

  # Only allow a list of trusted parameters through.
  def project_params
    params.require(:project).permit(:title, :image, :client, :brand, :category, :project_type, :description)
  end
end
