# frozen_string_literal: true

# Master Transcript Sections
class MasterSection < ApplicationRecord
  belongs_to :project, optional: true
  belongs_to :respondent_category, optional: true
  has_many :section_summaries, dependent: :destroy
  has_many :transcript_highlights, dependent: :nullify

  acts_as_list scope: :respondent_category_id

  NUMERICAL_ORDERING_SQL = "(extract_number_multi_separator(name))[1], (extract_number_multi_separator(name))[2], name"
  scope :numerical_order, -> { order(Arel.sql(NUMERICAL_ORDERING_SQL)) }

  include WordCloudable
  validates :name, presence: true

  def cloud_text
    TranscriptSection.where(name:, respondent_id: project.respondents.select(:id)).pluck(:content).join(" ")
  end

  def self.generate_sections_with_dg(dg_text, project_id, respondent_category_id)
    model_map = FeatureModelMap.find_by(feature_name: "DG_SECTIONS_GENERATION")
    chat = RubyLLM.chat(provider: model_map.provider, model: model_map.llm_model_name)

    system_prompt = <<~SYSTEM_PROMPT
      You are a market research analyst. You will be given a Discussion Guide (DG) which you will use as reference to create section headings.
      These section headings will be used to divide the transcripts in a market research study into sections.
      Write the section headers in such a way that, when these headers and a transcript is given to an LLM,
      it can easily divide the transcript into sections, based on these section headers.
      The headings must not contain section numbering.

      Return ONLY valid JSON with only 1 key "results", and an array of string values.
      Example response: {"results": ["Section heading 1", "Section heading 2"]}
    SYSTEM_PROMPT

    prompt = <<~PROMPT
      This is the DG:
      ```
      #{dg_text}
      ```
    PROMPT

    chat.with_instructions(system_prompt)
    response = chat.ask(prompt)

    json_match = response.content.match(/\{.*\}/m)
    unless json_match
      Rails.logger.error("No JSON found in LLM response")
      return
    end

    begin
      parsed_json = JSON.parse(json_match[0])
    rescue JSON::ParserError => e
      Rails.logger.error("Failed to parse JSON: #{e.message}")
      return
    end

    headings = parsed_json["results"]

    unless headings.is_a?(Array)
      Rails.logger.error("LLM response 'results' is not a valid array")
      return
    end

    headings.each do |heading|
      MasterSection.create!(name: heading, project_id:, respondent_category_id:)
    end

    task = SystemTask.where(task_type: "GenerateSectionsDG")
                     .where("metadata @> ?", { respondent_category_id: }.to_json)
                     .last

    return unless task

    task.update(status: "complete", running: false)

    respondent_category = RespondentCategory.find(respondent_category_id)

    # 1. Replace the button back to its active state
    Turbo::StreamsChannel.broadcast_replace_to(
      respondent_category, "tasks",
      target: "dg_sections_import_action_#{respondent_category.id}",
      partial: "respondent_categories/dg_sections_import_button",
      locals: { respondent_category:, sections_generating: false }
    )

    # 2. Append the JS trigger to tell Vue to fetch the new data
    Turbo::StreamsChannel.broadcast_append_to(
      respondent_category, "tasks",
      target: "dg_sections_import_action_#{respondent_category.id}",
      html: "<script>window.dispatchEvent(new CustomEvent('dg-sections-generated'));</script>"
    )

    SystemTask.execute_next_task!(task_class: task.task_class)
  end
end
