# frozen_string_literal: true

# Interview Questions
class InterviewQuestionsController < ApplicationController
  load_and_authorize_resource :respondent_category
  load_and_authorize_resource through: :respondent_category

  before_action :set_interview_question, only: %i[show edit update destroy]
  before_action :set_ancestors

  def get_questions # rubocop:disable Naming/AccessorMethodName
    render json: {
      status: "ok",
      questions: @respondent_category.interview_questions.order(:position)
    }
  end

  def import_with_dg
    require "pandoc-ruby"

    file = params[:file]

    if file.blank?
      redirect_back fallback_location: root_path, alert: "Please upload a .docx file."
      return
    end

    valid_mime_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
    unless file.content_type == valid_mime_type || file.original_filename.end_with?(".docx")
      redirect_back fallback_location: root_path, alert: "Only .docx files are allowed."
      return
    end

    begin
      extracted_text = PandocRuby.new([file.tempfile.path], from: :docx).to_plain

      GenerateQueriesWithDgJob.perform_later(
        metadata: { dg_text: extracted_text, respondent_category_id: @respondent_category.id },
        user_id: current_user.id
      )

      redirect_back fallback_location: root_path, notice: "Discussion Guide uploaded successfully. Generating queries..."
    rescue StandardError => e
      Rails.logger.error("Failed to parse docx file with Pandoc: #{e.message}")
      redirect_back fallback_location: root_path, alert: "There was an error reading the document."
    end
  end

  def import
    require "csv"

    file = params[:file]

    if file.blank?
      redirect_back fallback_location: root_path, alert: "Please upload a CSV file."
      return
    end

    # Basic validation to ensure it's a CSV
    unless file.content_type == "text/csv" || file.original_filename.end_with?(".csv")
      redirect_back fallback_location: root_path, alert: "Only CSV files are allowed."
      return
    end

    imported_count = 0

    begin
      # Read the CSV file
      CSV.foreach(file.path, headers: false) do |row|
        raw_name = row[0].to_s.strip

        # Skip empty rows or generic header labels
        next if raw_name.blank? || raw_name.downcase.in?(%w[name questions queries])

        # Sanitize the string: remove `, ', ", \
        sanitized_name = raw_name.gsub(/[`'"\\]/, "").strip

        # Skip if the sanitization left the string empty
        next if sanitized_name.blank?

        InterviewQuestion.create!(
          question: sanitized_name,
          respondent_category_id: @respondent_category.id
        )
        imported_count += 1
      end

      redirect_back fallback_location: root_path, notice: "Successfully imported #{imported_count} questions."
    rescue CSV::MalformedCSVError
      redirect_back fallback_location: root_path, alert: "The file could not be parsed. Please ensure it is a valid CSV."
    rescue StandardError => e
      redirect_back fallback_location: root_path, alert: "Error importing file: #{e.message}"
    end
  end

  def assign_sections
    params[:sections].each do |question_id, section_id|
      InterviewQuestion.find(question_id).update(master_section_id: section_id, assignable: false)
    end
    redirect_to project_respondent_category_interview_questions_path(@project, @respondent_category),
                notice: "Sections Assigned"
  end

  def reorder
    movement = params[:movement]
    respondent_category = RespondentCategory.find(params[:respondent_category_id])
    return render json: { status: "error" } if respondent_category.nil?

    interview_question = respondent_category.interview_questions.find(params[:id])
    return render json: { status: "error" } if interview_question.nil?

    if movement == "up"
      interview_question.move_higher
    else
      interview_question.move_lower
    end
    render json: { status: "ok",
                   updated_questions: respondent_category.interview_questions.where(assignable: false).order(:position).as_json(methods: :master_section_ids) }
  end

  def assignable
    @interview_questions = @respondent_category.interview_questions.where(assignable: true)
  end

  def bulk_delete
    @respondent_category.interview_questions.destroy_all
    redirect_to project_respondent_category_interview_questions_path(@project, @respondent_category),
                notice: "All Interview Questions in #{@respondent_category.name} have been deleted"
  end

  # GET /interview_questions or /interview_questions.json
  def index
    interview_questions = @respondent_category.interview_questions
                                              .includes(:master_sections)
                                              .where(assignable: false)
                                              .order(:position)

    gon.questions = interview_questions.as_json(methods: :master_section_ids)

    ordered_sections = MasterSection.where(respondent_category_id: @respondent_category.id)
                                    .order(:position)

    gon.master_sections = ordered_sections.index_by(&:id)
    gon.master_sections_order = ordered_sections.pluck(:id)

    gon.project_id = @respondent_category.project_id
    gon.respondent_category_id = @respondent_category.id

    task = SystemTask.where(task_type: "GenerateQueriesDG")
                     .where("metadata @> ?", { respondent_category_id: @respondent_category.id }.to_json)
                     .last
    @queries_generating = %w[queued running].include?(task&.status)
  end

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

  # GET /interview_questions/new
  def new
    @interview_question = @respondent_category.interview_questions.new
  end

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

  # POST /interview_questions or /interview_questions.json
  def create
    @interview_question = @respondent_category.interview_questions.new(interview_question_params)
    @interview_question.assignable = false

    respond_to do |format|
      if @interview_question.save
        @respondent_category.update!(requires_insight_regeneration: true)

        # HTML Response (Standard Forms)
        format.html do
          redirect_to [@project, @respondent_category, @interview_question],
                      notice: "Interview question was successfully created."
        end

        # Turbo Response (Hotwire)
        format.turbo_stream do
          @interview_questions = @respondent_category.interview_questions.order(created_at: :desc)
          render turbo_stream: turbo_stream.replace("questions_table", partial: "interview_questions/table")
        end

        # JSON Response (Vue.js / API)
        format.json do
          render json: {
            status: "ok",
            new_question: @interview_question.as_json(methods: :master_section_ids)
          }
        end
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: { status: "error", errors: @interview_question.errors }, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /interview_questions/1 or /interview_questions/1.json
  def update
    respond_to do |format|
      if @interview_question.update(interview_question_params)

        InsightsReport.update_questions_status(@interview_question.id)
        @respondent_category.update!(requires_insight_regeneration: true)

        format.html do
          redirect_to [@project, @respondent_category, @interview_question],
                      notice: "Interview question was successfully updated."
        end

        format.json do
          render json: { status: "ok" }
        end
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: { status: "error", errors: @interview_question.errors }, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /interview_questions/1 or /interview_questions/1.json
  def destroy
    question_id = @interview_question.id
    @interview_question.destroy

    InsightsReport.update_questions_status(question_id)
    @respondent_category.update!(requires_insight_regeneration: true)

    respond_to do |format|
      format.html do
        redirect_to project_respondent_category_interview_questions_path(@project, @respondent_category),
                    notice: "Interview question was successfully destroyed."
      end

      format.json do
        render json: { status: "ok" }
      end
    end
  end

  private

  def set_ancestors
    @project = Project.find(params[:project_id])
    @respondent_category = RespondentCategory.find(params[:respondent_category_id])
  end

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

  # Only allow a list of trusted parameters through.
  def interview_question_params
    params.require(:interview_question).permit(:respondent_category_id, :question, :respondent_category_id,
                                               master_section_ids: [])
  end
end
