# frozen_string_literal: true

# Respondents
class RespondentsController < ApplicationController
  load_and_authorize_resource :respondent_category
  load_and_authorize_resource through: :respondent_category

  before_action :set_respondent,
                except: %i[index new create upload_conversation cleanup_audio bulk_new bulk_download bulk_download_excel bulk_bookmark_generate bulk_summarize_transcripts bulk_summaries_download move]
  before_action :set_ancestors

  after_action :reset_category_assistant, only: %i[create destroy update_auto_transcript update_docx_transcript move]

  def move
    respondents = Respondent.where(id: params[:ids])
    current_project_id = params[:project_id].to_i
    target_project_id = params[:target_project_id]
    target_respondent_category_id = params[:target_respondent_category_id]

    target_respondent_category = RespondentCategory.find(target_respondent_category_id)

    # Pre-fetch existing master sections in the target category to minimize DB hits.
    # We use a hash for O(1) lookups: { "Section Name" => MasterSectionRecord }
    target_ms_cache = target_respondent_category.master_sections.index_by(&:name)

    begin
      Respondent.transaction do
        respondents.each do |respondent|
          # --- STEP 1: MIGRATE TRANSCRIPT SECTIONS AND HIGHLIGHTS ---

          # We need to map Old MasterSection IDs to New MasterSection IDs to update highlights later.
          # Structure: { old_id => new_id }
          ms_id_mapping = {}

          respondent.transcript_sections.each do |section|
            next if section.name.blank?

            # 1. Find or Create the matching MasterSection in the target category
            target_ms = target_ms_cache[section.name]

            if target_ms.nil?
              # Create if it doesn't exist
              target_ms = target_respondent_category.master_sections.create!(
                name: section.name,
                project_id: target_project_id
              )
              # Update cache so we don't try to create it again for the next section/respondent
              target_ms_cache[section.name] = target_ms
            end

            # 2. Record the mapping for Highlights
            # We must do this BEFORE updating the section, while it still has the old ID.
            ms_id_mapping[section.master_section_id] = target_ms.id if section.master_section_id.present?

            # 3. Update the TranscriptSection to point to the new MasterSection
            section.update!(master_section_id: target_ms.id)
          end

          # 4. Migrate TranscriptHighlights using the mapping
          # We only update highlights that have a master_section_id present in our map.
          ms_id_mapping.each do |old_id, new_id|
            respondent.transcript_highlights
                      .where(master_section_id: old_id)
                      .update_all(master_section_id: new_id)
          end

          # --- END OF STEP 1 ---

          # Step 2: Remove respondent_id from reports
          target_id = respondent.id

          SectionsReport.where("? = ANY(respondent_ids)", target_id).find_each do |report|
            report.remove_respondent!(target_id)
          end

          InsightsReport.where("? = ANY(respondent_ids)", target_id).find_each do |report|
            report.remove_respondent!(target_id)
          end

          ThemesReport.where("? = ANY(respondent_ids)", target_id).find_each do |report|
            report.remove_respondent!(target_id)
          end

          # step 3 - if the target project is different, remove the tags associated with the respondent
          respondent.tags.destroy_all if current_project_id != target_project_id

          # step 4 - change respondent_category_id of each selected respondent
          respondent.update!(respondent_category_id: target_respondent_category_id)
        end
      end

      render json: { message: "Respondents successfully moved." }, status: :ok
    rescue StandardError => e
      Rails.logger.error "Error while moving respondents - #{e.message}"
      render json: { message: "There was an error. Please contact the team." }, status: :internal_server_error
    end
  end

  def gcs_upload_url
    # For bulk uploads, find the respondent by ID
    respondent = if params[:respondent_id].present?
                   Respondent.find(params[:respondent_id])
                 else
                   @respondent # For single upload
                 end

    media_type = params[:media_type]
    content_type = params[:content_type]
    file_extension = params[:file_extension]

    render json: {
      upload_data: SprintGCS.signed_upload_url(
        path: respondent.attachment_gcs_path(media_type:, extension: file_extension),
        content_type:
      )
    }
  end

  def transcript_feedback
    @feedback = @respondent.whisper_transcript.feedback

    return unless request.post?

    if @respondent.whisper_transcript.update!(feedback: params[:respondent][:feedback])
      redirect_to(
        project_respondent_category_respondent_path(@project, @respondent_category, @respondent),
        notice: "Feedback submitted!"
      )
    else
      flash.now[:alert] = "Could not save feedback. Try again."
      render :transcript_feedback, status: :unprocessable_entity
    end
  end

  def translate_transcript
    GoogleTranslateJob.perform_later(
      respondent_id: @respondent.id,
      source_language_code: params[:language],
      target_language_code: "en"
    )
    redirect_to(
      project_respondent_category_respondent_path(
        @project,
        @respondent_category,
        @respondent
      ),
      notice: "Translation in process, please refresh this page in 5 minutes."
    )
  end

  def clone
    new_respondent = @respondent.dup
    new_respondent.audio_file = @respondent.audio_file
    new_respondent.video_file = @respondent.video_file
    new_respondent.transcript = @respondent.transcript
    new_respondent.first_name = "Copy of #{@respondent.name}"
    new_respondent.summary = nil

    # Preserve Tag Associations
    # This automatically creates the respondent_tags join records
    # for the new_respondent, linking it to the same tags as the original.
    new_respondent.tag_ids = @respondent.tag_ids

    new_respondent.save!

    # Clone Transcript Sections
    @respondent.transcript_sections.find_each do |section|
      new_section = section.dup
      new_section.respondent_id = new_respondent.id

      new_section.save!
    end

    if @respondent.docx_transcript
      docx_trans = @respondent.docx_transcript
      new_docx = docx_trans.dup
      new_docx.respondent_id = new_respondent.id
      new_docx.save!
    elsif @respondent.whisper_transcript
      whisper_trans = @respondent.whisper_transcript
      new_whisper = whisper_trans.dup
      new_whisper.respondent_id = new_respondent.id
      new_whisper.save!
    end

    redirect_to project_respondent_category_path(@project, @respondent_category),
                notice: "A copy of #{@respondent.name} has been created"
  end

  def reset_category_assistant
    @respondent_category.assistant_id = nil
    @respondent_category.index_name = nil
    @respondent_category.save

    @project.index_name = nil
    @project.save

    AssistantConversation.where(raggable: @respondent_category).update!(outdated: true)
    AssistantConversation.where(raggable: @project).update!(outdated: true)
  end

  def download_audio
    audio_url = @respondent.signed_audio_url
    redirect_to audio_url, allow_other_host: true
  rescue StandardError => e
    Rails.logger.error "Audio download failed: #{e.message}"
    render json: { error: "Download failed" }, status: :internal_server_error
  end

  def download_video
    video_url = @respondent.signed_video_url
    redirect_to video_url, allow_other_host: true
  rescue StandardError => e
    Rails.logger.error "Video download failed: #{e.message}"
    render json: { error: "Download failed" }, status: :internal_server_error
  end

  def cleanup_audio
    redirect_to [@respondent.project, @respondent.respondent_category, @respondent],
                notice: "Audio cleanup in progress.."
  end

  def transcript_sections; end

  def tag; end

  def insight_generator; end

  def upload_conversation
    @respondent = @respondent_category.respondents.new
  end

  def clear_tags
    @respondent.tags.each do |tag|
      @respondent.tags.delete(tag)
    end
    redirect_to [@project, @respondent_category, @respondent], notice: "Tags Cleared"
  end

  def update_tags
    @respondent.tags.each do |existing_tag|
      @respondent.tags.delete(existing_tag)
    end
    params[:tag_categories]&.each do |category_id, tag_id|
      category = TagCategory.find(category_id)
      if category.multiple_selections
        tag_id.each do |tid|
          @respondent.tags << Tag.find(tid) unless @respondent.tags.where(id: tid).exists?
        end
      else
        @respondent.tags << Tag.find(tag_id)
      end
    end
    redirect_to [@project, @respondent_category], notice: "Tags Updated"
  end

  def edit_docx_transcript
    gon.sections = @respondent.transcript_sections
    gon.utterances = @respondent.docx_transcript.verbose_json
    gon.master_sections = @project.relevant_master_sections
  end

  def edit_auto_transcript
    gon.sections = @respondent.transcript_sections
    gon.utterances = @respondent.whisper_transcript.verbose_json
    gon.master_sections = @project.relevant_master_sections
    gon.speakers = @respondent.original_speaker_map
  end

  def update_docx_transcript
    Rails.logger.debug "Sections - #{params[:sections]}".colorize(:yellow)
    transcript = @respondent.docx_transcript
    verbose_json = transcript.verbose_json

    params[:transcript].each do |index, text|
      verbose_json[index.to_i]["text"] = text
    end
    transcript.verbose_json = verbose_json
    transcript.save

    @respondent.transcript_highlights.destroy_all

    @respondent.transcript_sections.destroy_all
    sorted_sections = params[:sections]&.sort_by { |x| x[:offset].to_i }
    sorted_sections&.each_with_index do |section, i|
      offset = section[:offset].to_i
      previous_offset = sorted_sections[i - 1][:offset].to_i
      next_offset = if i == sorted_sections.size - 1
                      -1
                    else
                      sorted_sections[i + 1][:offset].to_i - 1
                    end
      Rails.logger.fatal("[SECTIONS] #{section[:name]} FROM #{offset} TO #{next_offset}")
      content = verbose_json[offset..next_offset].collect do |x|
        "#{x['speaker']}: #{x['text']}"
      end.join("\n\n")
      @respondent.transcript_sections.create(
        name: section[:name],
        offset:,
        content:,
        master_section_id: section[:master_section_id]
      )
    end

    redirect_to [@project, @respondent_category, @respondent], notice: "Transcript updated"
  end

  def update_auto_transcript
    transcript = @respondent.whisper_transcript
    verbose_json = transcript.verbose_json

    params[:utterances].each do |u|
      verbose_json[u[:index].to_i]["speaker"] = u[:speaker]
      verbose_json[u[:index].to_i]["text"] = u[:text]
    end
    transcript.verbose_json = verbose_json
    transcript.save

    @respondent.transcript_highlights.destroy_all
    @respondent.transcript_sections.destroy_all

    sorted_sections = params[:sections]&.sort_by { |x| x[:offset].to_i }
    sorted_sections&.each_with_index do |section, i|
      offset = section[:offset].to_i
      next_offset = i == sorted_sections.size - 1 ? -1 : sorted_sections[i + 1][:offset].to_i - 1
      content = verbose_json[offset..next_offset].collect { |x| "#{x['speaker']}: #{x['text']}" }.join("\n\n")
      @respondent.transcript_sections.create(
        name: section[:name],
        offset:,
        content:,
        master_section_id: section[:master_section_id]
      )
    end

    render json: { redirect: project_respondent_category_respondent_path(@project, @respondent_category, @respondent) }
  end

  def delete_sections
    @respondent.transcript_sections.destroy_all
    redirect_to [@project, @respondent_category, @respondent], notice: "Sections Deleted"
  end

  def create_sections
    TranscriptSection.create_from_respondent_transcript(@respondent)
    redirect_to [@project, @respondent_category, @respondent], notice: "Sections Created"
  end

  def speaker_map; end

  def remove_manual_transcript
    @respondent.transcript = nil
    @respondent.save
    redirect_to [@project, @respondent_category, @respondent], notice: "Manual Transcript Removed"
  end

  def remove_transcript
    @respondent.whisper_transcript.destroy
    @respondent.interview_insights.where(from_whisper: true).destroy_all
    @respondent.transcript_sections.destroy_all
    @respondent.transcript_highlights.destroy_all
    redirect_to [@project, @respondent_category, @respondent], notice: "Transcript archived."
  end

  def update_speaker_map
    speaker_map = params[:speaker_map] || {}
    delete_keys = params[:delete_speaker_map]&.keys || []

    cleaned_map = speaker_map.reject { |k, _| delete_keys.include?(k) }

    @respondent.update!(speaker_map: cleaned_map)
    redirect_to project_respondent_category_respondent_path(@project, @respondent_category, @respondent),
                notice: "Speaker Map Updated"
  end

  def add_speaker
    @respondent.speaker_map[params[:transcript_label]] = params[:new_label]
    @respondent.save
    redirect_to project_respondent_category_respondent_path(@project, @respondent_category, @respondent),
                notice: "Speaker Map Updated"
  end

  def generate_internal_transcript
    require "shellwords"

    duration = 0
    begin
      duration = `ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 -i #{Shellwords.escape(@respondent.audio_file.url)}`.strip.to_f / 60
      Rails.logger.debug("Audio Duration - #{duration} minutes")
    rescue StandardError => e
      Rails.logger.fatal("Error with Duration #{e.inspect}")
    end

    case @respondent.asr_model
    when "whisper-large-v3", "whisper-large-v2", "gemini-flash-002"
      flash[:alert] = "Model unsupported. Please select another model."
      return redirect_to [@project, @respondent_category]
    when "deepgram-nova"
      InternalTranscriptionV3Job.perform_later(@respondent.id, current_user.id)
    when "gladia"
      if duration > 135
        flash[:alert] = "Audio duration too long for this model. Transcription could not be queued."
        return redirect_to [@project, @respondent_category]
      end
      InternalTranscriptionV4Job.perform_later(@respondent.id, current_user.id)
    when "sarvam"
      InternalTranscriptionV5Job.perform_later(@respondent.id, current_user.id)
    when "voxtral"
      InternalTranscriptionV6Job.perform_later(@respondent.id, current_user.id)
    end

    sleep(1)
    flash[:notice] =
      "Your transcription task has been queued. Please wait until it has completed."
    redirect_to [@project, @respondent_category]
  end

  def queue_transcript_summarization
    @respondent.update!(summary: nil)
    TranscriptSummaryJob.perform_later(metadata: { respondent_id: @respondent.id }, user_id: current_user.id)
    redirect_to [@project, @respondent_category, @respondent], notice: "Transcript queued for summarization, please refresh the page after some time."
  end

  def queue_bookmark_generation
    if @respondent_category.master_sections.count.positive?
      GenerateBookmarksJob.perform_later(metadata: { respondent_id: @respondent.id }, user_id: current_user.id)
      redirect_to [@project, @respondent_category, @respondent], notice: "Transcript queued for bookmark generations, please refresh the page after some time."
    else
      redirect_to [@project, @respondent_category, @respondent], alert: "Bookmarks cannot be generated. No sections are created for this sub-project."
    end
  end

  def delete_insights
    @respondent.interview_insights.destroy_all
    redirect_to [@project, @respondent_category, @respondent],
                notice: "All insights have been deleted"
  end

  def index
    @respondents = @respondent_category.respondents.order(:created_at)
  end

  def docx_transcript
    @docx_transcript = @respondent.docx_transcript
  end

  def auto_transcript
    @whisper_transcript = @respondent.whisper_transcript
  end

  def download_summary
    if @respondent.summary.present?
      begin
        docx_data = MarkdownToDocxService.call(@respondent.summary, title: @respondent.name)

        if docx_data
          send_data docx_data,
                    filename: "#{@respondent.name.parameterize}_summary.docx",
                    type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                    disposition: "attachment"
        else
          Rails.logger.fatal("MarkdownToDocxService returned nil for Respondent #{@respondent.id}")
          flash[:alert] = "Error generating document. Please contact support."
          redirect_to [@project, @respondent_category, @respondent]
        end
      rescue StandardError => e
        Rails.logger.fatal("Transcript summary download error: #{e.inspect}")
        flash[:alert] = "Error. Please contact support."
        redirect_to [@project, @respondent_category, @respondent]
      end
    else
      flash[:alert] = "No Summary found"
      redirect_to [@project, @respondent_category, @respondent]
    end
  end

  def bulk_summaries_download
    require "zip"
    @respondents = Respondent.where(id: params[:ids])

    temp_zip = Tempfile.new(["bulk_summaries", ".zip"])

    begin
      Zip::File.open(temp_zip.path, Zip::File::CREATE) do |zipfile|
        @respondents.each do |respondent|
          next if respondent.summary.blank?

          docx_data = MarkdownToDocxService.call(respondent.summary, title: respondent.name)
          next if docx_data.nil?

          filename = "#{respondent.name.parameterize}_#{respondent.id}_summary.docx"

          zipfile.get_output_stream(filename) { |os| os.write docx_data }
        end
      end

      send_data File.binread(temp_zip.path),
                filename: "#{@respondent_category.name.parameterize}_summaries.zip",
                type: "application/zip",
                disposition: "attachment"
    ensure
      temp_zip.close
      temp_zip.unlink
    end
  end

  def download_transcript
    require "pandoc-ruby"

    sections = @respondent.transcript_sections.sort_by { |s| s["offset"] }

    # Initialize our Markdown string with the H1 Title
    markdown_content = "# #{@respondent.name}\n\n"

    if !@respondent.docx_transcript.nil?
      begin
        utterances = @respondent.docx_transcript.verbose_json

        if sections.empty?
          # No sections - output all utterances
          utterances.each do |sentence|
            cleaned_text = sentence["text"].gsub("\n", " ").strip
            markdown_content += "#{cleaned_text}\n\n"
          end
        else
          # Group utterances by section
          first_section_offset = sections[0]["offset"]

          # Handle utterances before first section (ungrouped)
          if first_section_offset.positive?
            (0...first_section_offset).each do |i|
              cleaned_text = utterances[i]["text"].gsub("\n", " ").strip
              markdown_content += "#{cleaned_text}\n\n"
            end
          end

          # Process sectioned utterances
          sections.each_with_index do |section, idx|
            markdown_content += "## #{section['name']}\n\n" # H2 Section Title

            section_start = section["offset"]
            section_end = idx < sections.length - 1 ? sections[idx + 1]["offset"] : utterances.length

            (section_start...section_end).each do |i|
              cleaned_text = utterances[i]["text"].gsub("\n", " ").strip
              markdown_content += "#{cleaned_text}\n\n"
            end
          end
        end

        # Convert Markdown string directly to Docx binary data
        docx_data = PandocRuby.new(markdown_content, from: :markdown).to_docx

        send_data docx_data,
                  filename: "#{@respondent.name.parameterize}.docx",
                  type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                  disposition: "attachment"
      rescue StandardError => e
        Rails.logger.fatal("Docx Transcript download error: #{e.inspect}")
        flash[:alert] = "Error. Try again later"
        redirect_to [@project, @respondent_category, @respondent]
      end

    elsif !@respondent.whisper_transcript.nil?
      begin
        utterances = @respondent.whisper_transcript.verbose_json
        speaker_map = @respondent.displayed_speaker_labels

        if sections.empty?
          # No sections - output all utterances
          @respondent.whisper_transcript.verbose_to_text.split("\n\n").each do |paragraph|
            cleaned_text = @respondent.sanitize_for_docx(paragraph)
            markdown_content += "#{cleaned_text}\n\n" if cleaned_text.present?
          end
        else
          # Group utterances by section
          first_section_offset = sections[0]["offset"]

          # Handle utterances before first section (ungrouped)
          if first_section_offset.positive?
            (0...first_section_offset).each do |i|
              utterance = utterances[i]
              speaker = speaker_map[utterance["speaker"]] || utterance["speaker"]
              text = "#{speaker}: #{utterance['text']}"
              cleaned_text = @respondent.sanitize_for_docx(text)
              markdown_content += "#{cleaned_text}\n\n" if cleaned_text.present?
            end
          end

          # Process sectioned utterances
          sections.each_with_index do |section, idx|
            markdown_content += "## #{section['name']}\n\n" # H2 Section Title

            section_start = section["offset"]
            section_end = idx < sections.length - 1 ? sections[idx + 1]["offset"] : utterances.length

            (section_start...section_end).each do |i|
              utterance = utterances[i]
              speaker = speaker_map[utterance["speaker"]] || utterance["speaker"]
              text = "#{speaker}: #{utterance['text']}"
              cleaned_text = @respondent.sanitize_for_docx(text)
              markdown_content += "#{cleaned_text}\n\n" if cleaned_text.present?
            end
          end
        end

        # Convert Markdown string directly to Docx binary data
        docx_data = PandocRuby.new(markdown_content, from: :markdown).to_docx

        send_data docx_data,
                  filename: "#{@respondent.name.parameterize}.docx",
                  type: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
                  disposition: "attachment"
      rescue StandardError => e
        Rails.logger.fatal("Whisper Transcript download error: #{e.inspect}")
        flash[:alert] = "Error. Try again later"
        redirect_to [@project, @respondent_category, @respondent]
      end
    else
      flash[:alert] = "No Transcript found"
      redirect_to [@project, @respondent_category, @respondent]
    end
  end

  def bulk_download_excel
    require "axlsx"
    @respondents = Respondent.where(id: params[:ids])

    p = Axlsx::Package.new
    p.use_shared_strings = true
    wb = p.workbook

    wb.styles do |s|
      header_style = s.add_style bg_color: "4472C4", fg_color: "FFFFFF", b: true

      wb.add_worksheet(name: "Transcripts") do |sheet|
        sheet.add_row ["Respondent Name", "Transcript"], style: [header_style, header_style]

        @respondents.each do |respondent|
          content = TranscriptGenerator.call_text(respondent)
          sheet.add_row [respondent.name, content.presence || ""]
        end
      end
    end

    send_data p.to_stream.read,
              filename: "#{@respondent_category.name.parameterize}_transcripts.xlsx",
              type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  end

  def bulk_download
    require "zip"
    @respondents = Respondent.where(id: params[:ids])

    temp_zip = Tempfile.new(["bulk_transcripts", ".zip"])

    begin
      Zip::File.open(temp_zip.path, Zip::File::CREATE) do |zipfile|
        @respondents.each do |respondent|
          content = TranscriptGenerator.call(respondent)
          next if content.nil?

          filename = "#{respondent.name.parameterize}_#{respondent.id}.docx"
          zipfile.get_output_stream(filename) { |f| f.write(content) }
        end
      end

      send_data File.binread(temp_zip.path),
                filename: "#{@respondent_category.name.parameterize}_transcripts.zip",
                type: "application/zip"
    ensure
      temp_zip.close
      temp_zip.unlink
    end
  end

  def bulk_bookmark_generate
    respondents = Respondent.where(id: params[:ids])
    if @respondent_category.master_sections.count.positive?
      respondents.each do |respondent|
        GenerateBookmarksJob.perform_later(metadata: { respondent_id: respondent.id }, user_id: current_user.id)
      end
      render json: { message: "Transcripts queued for bookmark generation. Please check after some time." }, status: :ok
    else
      render json: { message: "No sections found." }, status: :not_implemented
    end
  end

  def bulk_summarize_transcripts
    respondents = Respondent.where(id: params[:ids])
    respondents.each do |respondent|
      respondent.update!(summary: nil)
      TranscriptSummaryJob.perform_later(metadata: { respondent_id: respondent.id }, user_id: current_user.id) if respondent.transcript_available?
    end
    render json: { message: "Transcripts queued for summarization. Please check after some time." }, status: :ok
  end

  # GET /respondents/1 or /respondents/1.json
  def show
    @version = params[:version]&.to_i || 1
    gon.sections = @respondent.transcript_sections
    gon.master_sections = @respondent_category.master_sections.order(:position)
    gon.transcript_highlights = TranscriptHighlight.includes(:user).where(respondent_id: @respondent.id)
                                                   .select("transcript_highlights.*, (users.first_name || ' ' || users.last_name) as highlighted_by")
                                                   .joins(:user).as_json(methods: %i[processing
                                                                                     reel_available])

    gon.highlight_themes = HighlightTheme.where(respondent_category_id: @respondent_category.id)
                                         .order(:position)

    gon.project_id = @respondent_category.project_id
    gon.respondent_category_id = @respondent_category.id
    gon.respondent_id = @respondent.id
    gon.orgId = current_user.organization_id
    gon.audio_download_url = @respondent.signed_audio_url

    if !@respondent.whisper_transcript.nil?
      gon.utterances = @respondent.whisper_transcript.verbose_json
      gon.speakers = @respondent.original_speaker_map
      gon.display_speaker_map = @respondent.displayed_speaker_labels
      @is_manual = false
      gon.is_manual = @is_manual

      file_extension = File.extname(@respondent.audio_file.path)
      @mime_type = case file_extension.downcase
                   when ".mp3"
                     "audio/mpeg"
                   when ".ogg"
                     "audio/ogg"
                   when ".wav"
                     "audio/x-wav"
                   else
                     "audio/mpeg"
                   end
    elsif !@respondent.docx_transcript.nil?
      gon.utterances = @respondent.docx_transcript.verbose_json_indexed
      @is_manual = true
      gon.is_manual = @is_manual
    end
  end

  def archived_transcripts
    @soft_deleted_transcripts = WhisperTranscript.only_deleted.where(respondent_id: params[:id])
  end

  def restore_transcript
    @respondent = Respondent.find(params[:id])
    @transcript_to_restore = WhisperTranscript.only_deleted.find(params[:transcript_id])

    # Safety check: make sure the transcript actually belongs to the respondent
    unless @transcript_to_restore.respondent_id == @respondent.id
      redirect_to project_respondent_category_respondent_url(@project, @respondent_category, @respondent),
                  alert: "Transcript doesn't belong to this respondent."
    end

    # Soft delete the current active transcript
    @respondent.whisper_transcript.presence&.destroy

    # Restore the selected one
    @transcript_to_restore.recover

    redirect_to project_respondent_category_respondent_url(@project, @respondent_category, @respondent),
                notice: "Transcript restored successfully."
  end

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

  def bulk_finalize
    respondent_id = params[:id]
    uploaded_path = params[:uploaded_path]
    media_type = params[:media_type]

    respondent = Respondent.find(respondent_id)

    # Update paperclip metadata from GCS
    case media_type
    when "audio"
      update_paperclip_from_gcs(respondent, :audio_file, uploaded_path)
    when "video"
      update_paperclip_from_gcs(respondent, :video_file, uploaded_path)
      respondent.queue_video_conversion(user_id: current_user.id)
    when "transcript"
      update_paperclip_from_gcs(respondent, :transcript, uploaded_path)
      respondent.generate_docx_transcript!
    end

    render json: { status: "ok" }, status: :ok
  rescue StandardError => e
    Rails.logger.error("Error finalizing bulk upload: #{e.message}")
    render json: { error: e.message }, status: :internal_server_error
  end

  # GET /respondents/new
  def new
    @respondent = @respondent_category.respondents.new
    @respondent.proper_nouns = @respondent_category.respondents
                                                   .where.not(proper_nouns: []).last&.proper_nouns || []
  end

  # GET /respondents/1/edit
  def edit
    gon.language = @respondent.language
  end

  def create
    @respondent = @respondent_category.respondents.new(sanitized_params)
    @respondent.proper_nouns = respondent_params[:proper_nouns].first.split(",") if respondent_params[:proper_nouns]

    @respondent_category.update!(requires_section_regeneration: true, requires_insight_regeneration: true)

    respond_to do |format|
      if @respondent.save
        format.html do
          redirect_to [@project, @respondent_category],
                      notice: "Respondent was successfully created."
        end
        format.json do
          render json: { id: @respondent.id }, status: :created
        end
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @respondent.errors, status: :unprocessable_entity }
      end
    end
  end

  def update
    respond_to do |format|
      if @respondent.update(sanitized_params)
        if respondent_params[:proper_nouns].instance_of?(String)
          @respondent.proper_nouns = respondent_params[:proper_nouns].split(",").map(&:strip)
          @respondent.save
        end

        format.html do
          redirect_to project_respondent_category_respondent_url(@project, @respondent_category, @respondent),
                      notice: "Respondent was successfully updated."
        end
        format.json do
          render json: { status: "ok" }, status: :ok
        end
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @respondent.errors, status: :unprocessable_entity }
      end
    end
  end

  def finalize_upload
    uploaded_paths = params[:uploaded_paths] || {}

    # Update paperclip metadata from GCS
    update_paperclip_from_gcs(@respondent, :audio_file, uploaded_paths["audio"]) if uploaded_paths["audio"].present?

    if uploaded_paths["video"].present?
      update_paperclip_from_gcs(@respondent, :video_file, uploaded_paths["video"])
      @respondent.queue_video_conversion(user_id: current_user.id)
    end

    if uploaded_paths["transcript"].present?
      update_paperclip_from_gcs(@respondent, :transcript, uploaded_paths["transcript"])
      @respondent.generate_docx_transcript!
    end

    # Reset assistant if needed
    reset_category_assistant if uploaded_paths["audio"].present? || uploaded_paths["video"].present? || uploaded_paths["transcript"].present?

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

  # DELETE /respondents/1 or /respondents/1.json
  def destroy
    @respondent.destroy

    respond_to do |format|
      format.html do
        redirect_to [@project, @respondent_category],
                    notice: "Respondent was successfully deleted."
      end
      format.json { head :no_content }
    end
  end

  private

  def sanitized_params
    pars = respondent_params.to_h
    pars[:translate] = false if pars[:asr_model] == "deepgram-nova"
    pars
  end

  def update_paperclip_from_gcs(record, attachment_name, gcs_path)
    require "google/cloud/storage"

    filename = File.basename(gcs_path)

    storage = Google::Cloud::Storage.new
    bucket = storage.bucket("sprint-qualplatform")
    file = bucket.file(gcs_path)

    return unless file

    record.update_columns( # rubocop:disable Rails/SkipsModelValidations
      "#{attachment_name}_file_name" => filename,
      "#{attachment_name}_file_size" => file.size,
      "#{attachment_name}_content_type" => file.content_type,
      "#{attachment_name}_updated_at" => Time.current
    )
  end

  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_respondent
    @respondent = Respondent.find(params[:id])
  end

  # Only allow a list of trusted parameters through.
  def respondent_params
    params.require(:respondent).permit(:first_name, :last_name, :respondent_category_id, :transcript, :audio_file,
                                       :video_file, :language, :manual_language, :asr_model, :translate, :speaker_count, proper_nouns: [])
  end
end
