# typed: strict
# frozen_string_literal: true
class Domain::Post::InkbunnyPost < Domain::Post
  SUBMISSION_TYPE_MAP =
    T.let(
      {
        0 => "unknown",
        1 => "picture_pinup",
        2 => "sketch",
        3 => "picture_series",
        4 => "comic",
        5 => "portfolio",
        6 => "flash_animation",
        7 => "flash_interactive",
        8 => "video_feature",
        9 => "video_animation",
        10 => "music_single",
        11 => "music_album",
        12 => "writing_document",
        13 => "character_sheet",
        14 => "photography",
      }.freeze,
      T::Hash[Integer, String],
    )

  RATING_TYPE_MAP =
    T.let(
      { 0 => "general", 1 => "mature", 2 => "adult" }.freeze,
      T::Hash[Integer, String],
    )

  attr_json :ib_id, :integer
  attr_json :state, :string
  attr_json :rating, :string
  attr_json :submission_type, :string
  attr_json :title, :string
  attr_json :writing, :string
  attr_json :description, :string
  attr_json :num_views, :integer
  attr_json :num_files, :integer
  attr_json :num_favs, :integer
  attr_json :num_comments, :integer
  attr_json :keywords, ActiveModel::Type::Value.new
  attr_json :last_file_updated_at, ActiveModelUtcTimeValue.new
  attr_json :deep_update_log_entry_id, :integer
  attr_json :shallow_update_log_entry_id, :integer
  attr_json :shallow_updated_at, ActiveModelUtcTimeValue.new
  attr_json :deep_updated_at, ActiveModelUtcTimeValue.new
  attr_json :ib_detail_raw, ActiveModel::Type::Value.new

  has_multiple_files! Domain::PostFile::InkbunnyPostFile
  has_single_creator! Domain::User::InkbunnyUser
  has_faving_users! Domain::User::InkbunnyUser
  belongs_to_groups! :pools,
                     Domain::PostGroup::InkbunnyPool,
                     Domain::PostGroupJoin::InkbunnyPoolJoin
  belongs_to :deep_update_log_entry,
             class_name: "::HttpLogEntry",
             optional: true
  belongs_to :shallow_update_log_entry,
             class_name: "::HttpLogEntry",
             optional: true

  validates :ib_id, presence: true
  validates :state, presence: true, inclusion: { in: %w[ok error] }
  validates :rating, inclusion: { in: RATING_TYPE_MAP.values }, if: :rating
  validates :submission_type,
            inclusion: {
              in: SUBMISSION_TYPE_MAP.values,
            },
            if: :submission_type

  after_initialize do
    self.state ||= "ok"
    self.ib_detail_raw ||= {}
  end

  sig { override.returns([String, Symbol]) }
  def self.param_prefix_and_attribute
    ["ib", :ib_id]
  end

  sig { override.returns(String) }
  def self.view_prefix
    "ib"
  end

  sig { override.returns(Symbol) }
  def self.post_order_attribute
    :ib_id
  end

  sig { override.returns(String) }
  def description_html_base_domain
    "inkbunny.net"
  end

  sig { override.returns(Domain::DomainType) }
  def self.domain_type
    Domain::DomainType::Inkbunny
  end

  sig { override.returns(T.nilable(String)) }
  def description_html_for_view
    self.description
  end

  sig { override.returns(T.nilable(String)) }
  def title
    super
  end

  sig { override.returns(T.nilable(Domain::User)) }
  def primary_creator_for_view
    self.creator
  end

  sig { override.returns(T.nilable(HttpLogEntry)) }
  def scanned_post_log_entry_for_view
    self.deep_update_log_entry
  end

  sig { override.returns(T.nilable(T.any(String, Integer))) }
  def domain_id_for_view
    self.ib_id
  end

  sig { override.returns(T.nilable(String)) }
  def description_for_view
    # TODO - this is a mess, need to backfill descriptions on inkbunny posts
    description || self.ib_detail_raw&.dig("submission_json", "description") ||
      begin
        if contents = self.deep_update_log_entry&.response_bytes
          json = JSON.parse(contents)
          json["submissions"]
            .find { |s| s["submission_id"] == self.ib_id&.to_s }
            &.dig("description")
        end
      rescue StandardError
        nil
      end
  end

  sig { override.returns(T.nilable(Addressable::URI)) }
  def external_url_for_view
    if self.ib_id.present?
      Addressable::URI.parse("https://inkbunny.net/s/#{self.ib_id}")
    end
  end

  sig { override.returns(T.nilable(Domain::PostFile)) }
  def primary_file_for_view
    self.files.first
  end

  sig { override.returns(T.nilable(Integer)) }
  def num_favorites_for_view
    num_favs
  end
end
