class Recording < ApplicationRecord
  STATUSES = %w[processing ready expired failed].freeze
  PRIVACY_STATUSES = %w[public unlisted].freeze
  STORAGE_BACKENDS = %w[local s3].freeze

  belongs_to :stream_session
  belongs_to :team

  validates :status, inclusion: { in: STATUSES }
  validates :privacy_status, inclusion: { in: PRIVACY_STATUSES }
  validates :storage_backend, inclusion: { in: STORAGE_BACKENDS }

  scope :not_deleted, -> { where(deleted_at: nil) }
  scope :ready, lambda {
    not_deleted.where(status: "ready").where("expires_at IS NULL OR expires_at > ?", Time.current)
  }
  scope :publicly_listed, -> { where(privacy_status: "public") }
  scope :for_team, ->(team) { where(team: team) }
  scope :for_club, lambda { |club|
    joins(:team).where(teams: { club_id: club.id })
  }
  scope :expiring_within, lambda { |days|
    ready.where(expires_at: ..days.days.from_now)
  }
  scope :expired_pending_purge, lambda {
    not_deleted.where(status: %w[ready failed]).where("expires_at IS NOT NULL AND expires_at <= ?", Time.current)
  }
  scope :search_replays, lambda { |query|
    q = query.to_s.strip
    return all if q.blank?

    term = "%#{sanitize_sql_like(q)}%"
    joins(stream_session: { match: { team: :club } }).where(
      "recordings.title ILIKE :term OR teams.name ILIKE :term OR matches.opponent_name ILIKE :term OR clubs.name ILIKE :term OR matches.location ILIKE :term",
      term: term
    )
  }

  before_validation :normalize_privacy_status

  def replay_url
    return nil unless stream_session_id.present?
    return nil unless ready? || status == "processing"

    "#{MatchLiveTv.app_public_url.chomp('/')}/replay/#{stream_session_id}"
  end

  def playback_stream_url
    return nil unless ready? && stream_session_id.present?

    "#{MatchLiveTv.app_public_url.chomp('/')}/replay/#{stream_session_id}/stream"
  end

  def thumbnail_url
    return nil unless thumbnail_storage_key.present? && stream_session_id.present?

    "#{MatchLiveTv.app_public_url.chomp('/')}/replay/#{stream_session_id}/thumbnail"
  end

  def download_api_path
    return nil unless ready?

    "/api/v1/recordings/#{id}/download"
  end

  def youtube_watch_url
    return nil if youtube_video_id.blank?
    return nil if youtube_video_id.to_s.start_with?("mock_")

    "https://www.youtube.com/watch?v=#{youtube_video_id}"
  end

  def ready?
    status == "ready" && !deleted? && (expires_at.nil? || expires_at.future?)
  end

  def deleted?
    deleted_at.present?
  end

  def publicly_listed?
    privacy_status == "public"
  end

  def unlisted?
    privacy_status == "unlisted"
  end

  def auto_publish_youtube?
    metadata.is_a?(Hash) && metadata["auto_publish_youtube"] == true
  end

  def ai_metadata
    metadata.fetch("ai", {})
  end

  def merge_metadata!(attrs)
    update!(metadata: metadata.merge(attrs.stringify_keys))
  end

  def title_or_default
    title.presence || default_title
  end

  def default_title
    match = stream_session&.match
    return "Replay" unless match

    "#{match.team.name} vs #{match.opponent_name}"
  end

  def recorded_at_or_fallback
    recorded_at || stream_session&.ended_at || stream_session&.started_at || created_at
  end

  def duration_label
    return "—" if duration_secs.to_i <= 0

    mins = duration_secs / 60
    secs = duration_secs % 60
    format("%d:%02d", mins, secs)
  end

  def byte_size_label
    bytes = byte_size.to_i
    return "—" if bytes <= 0

    if bytes >= 1.gigabyte
      format("%.1f GB", bytes / 1.gigabyte.to_f)
    elsif bytes >= 1.megabyte
      format("%.1f MB", bytes / 1.megabyte.to_f)
    else
      format("%.0f KB", bytes / 1.kilobyte.to_f)
    end
  end

  def views_label
    count = view_count.to_i
    return "0 visualizzazioni" if count.zero?

    count == 1 ? "1 visualizzazione" : "#{count} visualizzazioni"
  end

  def status_label
    return "Eliminato" if deleted?
    return "Scaduto" if status == "expired"
    return "Errore" if status == "failed"
    return "In elaborazione" if status == "processing"
    return "Scade presto" if expires_at.present? && expires_at <= 7.days.from_now

    "Disponibile"
  end

  private

  def normalize_privacy_status
    self.privacy_status = "public" if privacy_status == "private"
    self.privacy_status = "unlisted" if privacy_status.blank?
  end
end
