require "net/http"
require "uri"
require "json"
require "tempfile"

class AiModeratorsController < ApplicationController
  before_action :set_ancestors, except: [:upload_audio]
  skip_before_action :verify_authenticity_token, only: [:upload_audio]

  def upload_audio
    api_key = request.headers["X-Partner-API-Key"]

    return render status: :forbidden, json: { error: "Invalid API Key" } if Rails.application.credentials.ai_moderator_api_key != api_key

    existing_respondent = Respondent.find_by(ai_moderator_id: params[:conversation_id])

    return render json: { status: "ok" } if existing_respondent

    recording = download_recording(params.require(:recording))

    respondent = Respondent.create!(
      ai_moderator_id: params[:conversation_id],
      first_name: params[:respondent_name], # TODO: Eventually split this
      language: params[:language],
      recording_duration_seconds: params[:recording_duration_seconds],
      # TODO: Set asr_model here based on some logic,
      respondent_category_id: params[:respondent_category_id],
      audio_file: recording
    )

    render json: { status: "ok", respondent_id: respondent.id }
  rescue StandardError => e
    render json: { status: "error", message: e.message }
  ensure
    recording&.close!
  end

  def initialize_integration
    @ai_moderator = @respondent_category.build_ai_moderator(ai_moderator_params)
    @ai_moderator.session_name = @respondent_category.name
    @ai_moderator.moderator_name = nil

    uploaded_file = params[:discussion_guide_file]

    # Pre-validate the uploaded file extension before hitting the API
    if uploaded_file.present?
      ext = File.extname(uploaded_file.original_filename).delete(".").downcase
      unless %w[pdf docx].include?(ext)
        @ai_moderator.errors.add(:base, "Discussion guide file must be a PDF or DOCX.")
        render_setup_page_with_errors
        return
      end
    end

    if @ai_moderator.valid?
      # Pass the uploaded file to the API method
      api_response = create_mentza_integration(@ai_moderator, uploaded_file)

      if api_response[:status] == "ok"
        @ai_moderator.launch_link = api_response.dig(:data, :url)
        @ai_moderator.mentza_moderator_id = api_response.dig(:data, :id)

        if @ai_moderator.save
          if uploaded_file.present?
            @respondent_category.research_documents.create(
              document: uploaded_file,
              discussion_guide: true
            )
          end

          redirect_to project_setup_project_respondent_category_path(@project, @respondent_category), notice: "AI Moderator successfully initialized."
          return
        end
      else
        error_msg = api_response[:message].presence || "Failed to create integration"
        @ai_moderator.errors.add(:base, error_msg)
      end
    end

    render_setup_page_with_errors
  end

  private

  def download_recording(url)
    uri = URI.parse(url)
    raise ArgumentError, "Recording URL must use HTTP or HTTPS" unless uri.is_a?(URI::HTTP) && uri.host.present?

    filename = File.basename(uri.path.presence || "recording")
    filename = "recording" if ["/", "."].include?(filename)
    recording = Tempfile.new(["ai_moderator_recording", File.extname(filename)])
    recording.binmode

    response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", open_timeout: 10, read_timeout: 120) do |http|
      http.request(Net::HTTP::Get.new(uri.request_uri)) do |http_response|
        raise "Recording download failed with HTTP #{http_response.code}" unless http_response.is_a?(Net::HTTPSuccess)

        http_response.read_body { |chunk| recording.write(chunk) }
        http_response
      end
    end

    recording.rewind
    recording.define_singleton_method(:original_filename) { filename }
    recording.define_singleton_method(:content_type) { response["Content-Type"] }
    recording
  rescue StandardError
    recording&.close!
    raise
  end

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

  def ai_moderator_params
    params.require(:ai_moderator).permit(
      :research_objectives, :target_group, :opening_stmt, :closing_stmt, :sample_size, :moderator_identity
    )
  end

  def render_setup_page_with_errors
    @research_documents = @respondent_category.research_documents.order(created_at: :desc)
    @existing_guide = @respondent_category.research_documents.exists?(discussion_guide: true)
    render "respondent_categories/project_setup", status: :unprocessable_entity
  end

  def create_mentza_integration(moderator, uploaded_file)
    uri = URI("https://business.mentza.com/api/v1/integrations/partner/a_i_moderators")
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true

    raise "AI Moderator API Key Missing" if Rails.application.credentials.ai_moderator_api_key.blank?

    request = Net::HTTP::Post.new(uri)
    request["X-Partner-API-Key"] = Rails.application.credentials.ai_moderator_api_key

    # The partner API expects moderator attributes under params[:ai_moderator].
    form_data = [
      ["project_id", @project.id.to_s],
      ["respondent_category_id", @respondent_category.id.to_s],
      ["ai_moderator[project_id]", @project.id.to_s],
      ["ai_moderator[project_name]", @project.title],
      ["ai_moderator[session_name]", moderator.session_name.to_s],
      ["ai_moderator[research_objectives]", moderator.research_objectives.to_s],
      ["ai_moderator[target_group]", moderator.target_group.to_s],
      ["ai_moderator[opening_stmt]", moderator.opening_stmt.to_s],
      ["ai_moderator[closing_stmt]", moderator.closing_stmt.to_s],
      ["ai_moderator[sample_size]", moderator.sample_size.to_s],
      ["ai_moderator[moderator_identity]", moderator.moderator_identity.to_s]
    ]

    # Attach the file safely
    if uploaded_file.present?
      # Scenario A: User uploaded a brand new file in the form
      form_data << [
        "discussion_guide",
        uploaded_file.tempfile,
        { filename: uploaded_file.original_filename, content_type: uploaded_file.content_type }
      ]
    else
      # Scenario B: User did not upload a new file, check for an existing one
      existing_guide = moderator.discussion_guide_document

      if existing_guide.present?
        url = existing_guide.document.url
        filename = existing_guide.document_file_name

        if url.match?(%r{\Ahttps?://})
          doc_uri = URI.parse(url)
          doc_http = Net::HTTP.new(doc_uri.host, doc_uri.port)
          doc_http.use_ssl = (doc_uri.scheme == "https")

          doc_response = doc_http.request_get(doc_uri.request_uri)
          file_stream = StringIO.new(doc_response.body)
        end

        form_data << [
          "discussion_guide",
          file_stream,
          { filename: filename }
        ]
      end
    end

    # Encode as multipart/form-data and execute
    request.set_form(form_data, "multipart/form-data")

    response = http.request(request)
    Rails.logger.info("Mentza status: #{response.code}")
    Rails.logger.info("Mentza body: #{response.body[0..500]}")
    JSON.parse(response.body).with_indifferent_access
  rescue StandardError => e
    { status: "error", message: "Network error: #{e.message}" }.with_indifferent_access
  ensure
    # Clean up file streams
    file_stream&.close if defined?(file_stream) && file_stream.respond_to?(:close)
  end
end
