# frozen_string_literal: true

# Reel Model
class Reel < ApplicationRecord
  belongs_to :respondent_category

  has_attached_file :video, validate_media_type: false
  has_attached_file :audio, validate_media_type: false
  do_not_validate_attachment_file_type :video
  do_not_validate_attachment_file_type :audio

  enum :reel_type, { audio: "audio", video: "video" }

  def stitch_reels(system_task_id:, reel_id:, highlight_ids:, subtitles_enabled:)
    require "google/cloud/run/v2"

    reel = Reel.find_by(id: reel_id)

    return if reel.nil?

    job_type = "STITCH_REEL"

    notification_url = "https://analysis.sprintstudio.ai/api/cloud_job_finish"
    error_notification_url = "https://analysis.sprintstudio.ai/api/cloud_job_error"

    output_gcs_uri = "gs://sprint-qualplatform/#{reel_path_for(reel_id, subtitles_enabled, reel.reel_type)}"

    client = Google::Cloud::Run::V2::Jobs::Client.new
    project_id = "norse-baton-398712"
    region = "asia-south1"
    parent = "projects/#{project_id}/locations/#{region}"
    job_name = "video-processor-job"

    highlights = TranscriptHighlight.where(id: highlight_ids).in_order_of(:id, highlight_ids).index_by(&:id)
    source_media_gcs_uris = highlights.map { |_id, highlight| "gs://sprint-qualplatform/#{highlight.reel.path}" }

    result = []
    cumulative_time = 0.0

    Rails.logger.debug("[Stitching Reel] Generating data structure for subtitles...")
    highlights.each_value do |highlight|
      # Get all segments for this highlight
      segments = highlight.content.map do |segment|
        # Skip segments with empty text
        next if segment["text"].nil? || segment["text"].strip.empty?

        {
          text: segment["text"],
          original_start: segment["start"],
          original_end: segment["end"]
        }
      end.compact

      next if segments.empty?

      # Get the first segment's start time to use as the baseline for this highlight
      highlight_start_offset = segments.first[:original_start]

      # Process each segment in this highlight
      segments.each do |segment|
        # Normalize timestamps relative to this highlight's start (preserves gaps within highlight)
        relative_start = segment[:original_start] - highlight_start_offset
        relative_end = segment[:original_end] - highlight_start_offset

        # Create the new segment with recalculated  timestamps
        # Because the highlights will be stitched and the timestamps must be relative to the stitched reel and not the original video
        result << {
          text: segment[:text],
          start: cumulative_time + relative_start,
          end: cumulative_time + relative_end
        }
      end
      # Update cumulative time to where this highlight ends
      # Next highlight should start exactly where this highlight's last segment ends
      highlight_duration = segments.last[:original_end] - highlight_start_offset
      cumulative_time += highlight_duration
    end
    Rails.logger.debug("[Stitching Reel] Updating reel data")

    reel.update!(data: result, highlight_ids:)

    Rails.logger.debug("[Stitching Reel] Sending data to GCP for stitching")
    json_payload = {
      job_type:,
      notification_url:,
      error_notification_url:,
      system_task_id:,
      reel_id: reel.id,
      reel_data: reel.data,
      reel_type: reel.reel_type,
      subtitles_enabled:,
      source_media_gcs_uris:,
      output_gcs_uri:
    }.to_json

    Rails.logger.debug("Reel Creation payload -> #{json_payload}")
    request = Google::Cloud::Run::V2::RunJobRequest.new(
      name: "#{parent}/jobs/#{job_name}",
      overrides: {
        container_overrides: [
          {
            args: [json_payload]
          }
        ]
      }
    )

    operation = client.run_job request
    Rails.logger.info "Started Cloud Run Job. Operation name: #{operation.name}"
  rescue Google::Cloud::Error => e
    Rails.logger.error "Failed to run Cloud Run Job: #{e.message}"
  end

  def video_url_unsigned
    video.url
  end

  def audio_url_unsigned
    audio.url
  end

  def processing
    task = SystemTask.where(task_type: "StitchedReelCreation").where("metadata @> ?",
                                                                     { reel_id: id }.to_json).last
    return false if task.nil?

    %w[queued running].include?(task.status.downcase)
  end

  def reel_available
    !video_file_name.nil?
  end

  private

  def reel_path_for(reel_id, subtitles_enabled, reel_type)
    require "securerandom"
    id_partition = format("%09d", reel_id).scan(/\d{3}/).join("/")

    uuid = SecureRandom.uuid

    subtitle_status = subtitles_enabled ? "subbed" : "unsubbed"

    if reel_type == "video"
      "reels/videos/#{id_partition}/original/reel_#{subtitle_status}_#{uuid}.mp4"
    else
      "reels/audios/#{id_partition}/original/reel_#{uuid}.mp3"
    end
  end
end
