# typed: strict
class Domain::User::FaUser < Domain::User
  aux_table :fa

  due_timestamp :scanned_gallery_at, 3.years
  due_timestamp :scanned_page_at, 3.months
  due_timestamp :scanned_follows_at, 3.months
  due_timestamp :scanned_followed_by_at, 3.months
  due_timestamp :scanned_incremental_at, 1.month

  # todo - set this to be the right fav model type
  has_many :user_post_favs,
           class_name: "Domain::UserPostFav",
           foreign_key: :user_id,
           inverse_of: :user

  belongs_to :last_user_page_log_entry,
             foreign_key: :last_user_page_id,
             class_name: "::HttpLogEntry",
             optional: true

  belongs_to :last_gallery_page_log_entry,
             foreign_key: :last_gallery_page_id,
             class_name: "::HttpLogEntry",
             optional: true

  has_followed_users! Domain::User::FaUser
  has_followed_by_users! Domain::User::FaUser
  has_created_posts! Domain::Post::FaPost
  has_faved_posts! Domain::Post::FaPost

  enum :state,
       { ok: "ok", account_disabled: "account_disabled", error: "error" },
       prefix: :state

  validates :name, presence: true
  validates :url_name, presence: true
  validates :state, presence: true

  # validates :account_status,
  #           inclusion: {
  #             in: %w[active suspended banned deceased],
  #             allow_nil: true,
  #           }

  after_initialize { self.state ||= "ok" if new_record? }

  sig { override.returns(T.class_of(Domain::UserPostFav)) }
  def self.fav_model_type
    Domain::UserPostFav::FaUserPostFav
  end

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

  sig { void }
  def thing
    Domain::User::FaUser.where(url_name: "test")
  end

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

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

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

  sig { override.returns(String) }
  def site_name_for_view
    "Furaffinity"
  end

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

  sig { override.returns(T::Array[String]) }
  def names_for_search
    [name, url_name, full_name].compact
  end

  sig do
    params(
      submission_parser:
        T.any(
          Domain::Fa::Parser::ListedSubmissionParserHelper,
          Domain::Fa::Parser::SubmissionParserHelper,
        ),
    ).returns(Domain::User::FaUser)
  end
  def self.find_or_build_from_submission_parser(submission_parser)
    find_or_initialize_by(url_name: submission_parser.artist_url_name) do |user|
      user.name = submission_parser.artist
    end
  end

  sig do
    params(
      post_id: Integer,
      fav_id: T.nilable(Integer),
      explicit_time: T.nilable(Time),
    ).returns(Domain::UserPostFav)
  end
  def update_fav_model(post_id:, fav_id: nil, explicit_time: nil)
    model =
      self.user_post_favs.find_by(post_id:) ||
        self.user_post_favs.build(
          type: self.class.fav_model_type.name,
          post_id:,
        )
    if model.is_a?(Domain::UserPostFav::FaUserPostFav)
      model.fav_id = fav_id if fav_id.present?
      model.explicit_time = explicit_time if explicit_time.present?
      model.save!
    end
    model
  end

  # TODO - write a test for this
  sig { override.returns(String) }
  def account_status_for_view
    as =
      account_status ||
        begin
          if (hle = guess_last_user_page_log_entry)
            parser =
              Domain::Fa::Parser::Page.from_log_entry(
                hle,
                require_logged_in: false,
              )
            parser.user_page.account_status.to_s if parser.probably_user_page?
          end
        end || "unknown"
    as.titlecase
  end

  sig { returns(String) }
  def account_state_for_view
    case state
    when "ok"
      "Ok"
    when "account_disabled"
      "Disabled"
    when "error"
      "Error"
    else
      "Unknown"
    end
  end

  sig { returns(T.nilable(HttpLogEntry)) }
  def guess_last_user_page_log_entry
    last_user_page_log_entry ||
      HttpLogEntry.find_by_uri_host_path(
        "https://www.furaffinity.net/user/#{url_name}/",
      ) ||
      HttpLogEntry.find_by_uri_host_path(
        "https://www.furaffinity.net/user/#{url_name}",
      )
  end

  sig { override.returns(T.nilable(String)) }
  def external_url_for_view
    "https://www.furaffinity.net/user/#{url_name}" if url_name.present?
  end

  sig { override.returns(T.nilable(String)) }
  def name_for_view
    name || url_name
  end
end
