class WhisperTranscript < ApplicationRecord
  acts_as_paranoid

  belongs_to :respondent

  after_create :create_original_speaker_mapping!

  include WordCloudable

  def self.purge_archived_transcripts
    PurgeArchivedTranscriptsJob.perform_later
  end

  def create_original_speaker_mapping!
    mapped_labels = respondent.mapped_labels(self)
    respondent.update!(original_speaker_map: mapped_labels)
  rescue StandardError => e
    Rails.logger.fatal("Error while creating original speaker mapping -> #{e.inspect}")
  end

  # Similar to verbose_to_mapped, but also preserves word level speaker info
  def verbose_speaker_mapped
    raw_json = self[:verbose_json]
    return raw_json unless raw_json.present? && respondent&.speaker_map.present?

    transform_speakers(raw_json)
  end

  def transform_speakers(json_data)
    json_data.map do |segment|
      # Clone the segment to avoid mutating the original data
      new_segment = segment.dup

      # Replace the speaker using the speaker_map
      new_segment["speaker"] = respondent.speaker_map[segment["speaker"]] if segment["speaker"].present? && respondent.speaker_map[segment["speaker"]].present?

      # Transform speakers in words array if it exists
      if segment["words"].present?
        new_segment["words"] = segment["words"].map do |word|
          word_copy = word.dup
          word_copy["speaker"] = respondent.speaker_map[word["speaker"]] if word["speaker"].present? && respondent.speaker_map[word["speaker"]].present?
          word_copy
        end
      end

      new_segment
    end
  end

  def cloud_text
    verbose_to_text
  end

  def relabel_speaker(old_label, new_label)
    verbose_json.each do |row|
      row["speaker"] = new_label if row["speaker"] == old_label
    end
    save
  end

  def text_for_highlight
    sorted_data = verbose_json.sort_by { |item| item["start"] }

    sorted_data.map do |entry|
      {
        start: entry["start"],
        speaker: entry["speaker"],
        text: entry["text"],
        words: entry["words"]
               .select { |word| word["start"] } # Exclude words with nil start
               .sort_by { |word| word["start"] }
               .map { |word| word.slice("start", "end", "word") }
      }
    end
  end

  def verbose_to_text
    mapped = verbose_to_mapped
    result = ""
    mapped.each do |row|
      result << "#{respondent.mapped_name(row[:speaker])}: #{row[:text]}\n\n"
    end
    result
  end

  def ifw_verbose_to_mapped
    result = []
    current_speaker = nil
    current_speech = ""
    previous_text = ""

    sorted_transcript = verbose_json.sort_by { |x| x["timestamp"].first }
    sorted_transcript.each do |row|
      if current_speaker != row["speaker"]
        # Add the previous speaker's speech to the result, unless it's the first iteration
        result << { speaker: current_speaker, text: current_speech } unless current_speaker.nil?

        # Reset for new speaker
        current_speaker = row["speaker"]
        current_speech = ""
        previous_text = ""
      end

      # Construct the speech line from words and check for repetitions
      speech_line = row["text"]
      unless speech_line == previous_text
        current_speech << " #{speech_line}"
        previous_text = speech_line
      end
    end
    result << { speaker: current_speaker, text: current_speech } unless current_speaker.nil?
    result
  end

  def verbose_to_mapped
    first_row = verbose_json.first
    return sarvam_verbose_to_mapped if respondent.asr_model == "sarvam"
    return ifw_verbose_to_mapped unless first_row.key?("end")

    result = []
    current_speaker = nil
    current_speech = ""
    previous_text = ""

    verbose_json.sort_by { |x| x["start"] }.each do |row|
      # Check if the speaker has changed
      if current_speaker != row["speaker"]
        # Add the previous speaker's speech to the result, unless it's the first iteration
        result << { speaker: current_speaker, text: current_speech.strip } unless current_speaker.nil?

        # Reset for new speaker
        current_speaker = row["speaker"]
        current_speech = ""
        previous_text = ""
      end

      # Construct the speech line from words, falling back to row["text"] if words is empty
      words = row["words"] || []
      speech_line = words.any? ? words.map { |word| word["word"] }.join(" ") : row["text"].to_s

      unless speech_line == previous_text
        current_speech << " #{speech_line}"
        previous_text = speech_line
      end
    end

    # Add the last speaker's speech to the result
    result << { speaker: current_speaker, text: current_speech.strip } unless current_speaker.nil?
    result
  end

  def sarvam_verbose_to_mapped
    result = []
    current_speaker = nil
    current_speech = ""
    previous_text = ""

    verbose_json.sort_by { |x| x["start"] }.each do |row|
      # Check if the speaker has changed
      if current_speaker != row["speaker"]
        # Add the previous speaker's speech to the result, unless it's the first iteration
        result << { speaker: current_speaker, text: current_speech } unless current_speaker.nil?

        # Reset for new speaker
        current_speaker = row["speaker"]
        current_speech = ""
        previous_text = ""
      end

      # Get the speech line directly from the text field
      speech_line = row["text"] || ""
      unless speech_line == previous_text
        current_speech << " #{speech_line}"
        previous_text = speech_line
      end
    end

    # Add the last speaker's speech to the result
    result << { speaker: current_speaker, text: current_speech } unless current_speaker.nil?
    result
  end
end
