require "set"

module Mediamtx
  class Client
    class Error < StandardError; end

    def initialize(base_url: MatchLiveTv.mediamtx_api_url)
      @conn = Faraday.new(url: base_url) do |f|
        f.request :json
        f.response :json
        f.adapter Faraday.default_adapter
      end
    end

    def create_path(session)
      path = session.mediamtx_path_name
      record = session.match.team.entitlements.recording_enabled_for_mediamtx?
      body = {
        source: "publisher",
        overridePublisher: true,
        record: record,
        recordPath: "/recordings/%path/%Y-%m-%d_%H-%M-%S",
        recordSegmentDuration: "60s"
      }
      unless session.matchlivetv_platform?
        body[:runOnReady] = run_on_ready_script(session)
        body[:runOnReadyRestart] = true
        body[:runOnNotReady] = webhook_curl(session, "disconnect")
      end
      response = @conn.post("/v3/config/paths/add/#{CGI.escape(path)}", body)
      unless response.success?
        err = response.body.is_a?(Hash) ? response.body["error"] : response.body
        raise Error, "MediaMTX path create failed: #{response.status} #{err}"
      end
      true
    end

    def delete_path(session)
      delete_path_name(session.mediamtx_path_name)
    end

    def delete_path_name(path_name)
      @conn.post("/v3/config/paths/delete/#{CGI.escape(path_name)}")
    end

    def list_paths
      response = @conn.get("/v3/paths/list")
      return [] unless response.success?

      body = response.body
      body.is_a?(Hash) ? (body["items"] || []) : []
    rescue Error, Faraday::Error
      []
    end

    def online_path_names
      Set.new(list_paths.filter_map { |item| item["name"] if item["online"] })
    end

    private

    def publish_webhook(session)
      webhook_curl(session, "connect")
    end

    def disconnect_webhook(session)
      webhook_curl(session, "disconnect")
    end

    def webhook_curl(session, event)
      secret = MatchLiveTv.mediamtx_webhook_secret
      rails = ENV.fetch("RAILS_WEBHOOK_URL", "http://rails:3000")
      payload = %({"session_id":"#{session.id}"})
      # MediaMTX image non include curl; wget è disponibile nell'immagine ufficiale
      <<~SCRIPT.squish
        wget -q -O- --post-data='#{payload}' --header='Content-Type: application/json'
        --header="X-MediaMTX-Signature: $(printf '%s' '#{payload}' | openssl dgst -sha256 -hmac '#{secret}' | cut -d' ' -f2)"
        #{rails}/webhooks/mediamtx/#{event}
      SCRIPT
    end

    def run_on_ready_script(session)
      connect = webhook_curl(session, "connect")
      return connect if session.matchlivetv_platform?

      "#{connect} & #{relay_script(session)}"
    end

    def relay_script(session)
      return "echo 'no youtube key'" if session.stream_key.blank?
      return "echo 'youtube relay skipped'" unless session.platform == "youtube"

      key = session.stream_key
      path = session.mediamtx_path_name
      <<~SCRIPT.squish
        ffmpeg -re -i rtmp://127.0.0.1:1935/#{path} -c copy -f flv
        rtmp://a.rtmp.youtube.com/live2/#{key} 2>/var/log/ffmpeg-#{path}.log
      SCRIPT
    end
  end
end
