# typed: strict
class DomainController < ApplicationController
  extend T::Sig
  extend T::Helpers
  abstract!

  class DomainParamConfig < T::ImmutableStruct
    include T::Struct::ActsAsComparable

    const :post_id_param, Symbol
    const :user_id_param, Symbol
    const :post_group_id_param, Symbol
  end

  sig { void }
  def initialize
    super
    @post = T.let(nil, T.nilable(Domain::Post))
    @user = T.let(nil, T.nilable(Domain::User))
    @post_group = T.let(nil, T.nilable(Domain::PostGroup))
  end

  protected

  sig { abstract.returns(DomainParamConfig) }
  def self.param_config
  end

  sig(:final) { void }
  def set_post!
    @post =
      self.class.find_model_from_param(
        Domain::Post,
        params[self.class.param_config.post_id_param],
      ) || raise(ActiveRecord::RecordNotFound)
  end

  sig(:final) { void }
  def set_user!
    @user =
      self.class.find_model_from_param(
        Domain::User,
        params[self.class.param_config.user_id_param],
      ) || raise(ActiveRecord::RecordNotFound)
  end

  sig(:final) { void }
  def set_post_group!
    @post_group =
      self.class.find_model_from_param(
        Domain::PostGroup,
        params[self.class.param_config.post_group_id_param],
      ) || raise(ActiveRecord::RecordNotFound)
  end

  public

  sig(:final) do
    type_parameters(:Klass)
      .params(
        klass:
          T.all(
            T.class_of(ReduxApplicationRecord),
            HasCompositeToParam::ClassMethods[T.type_parameter(:Klass)],
          ),
        param: T.nilable(String),
      )
      .returns(T.nilable(T.type_parameter(:Klass)))
  end
  def self.find_model_from_param(klass, param)
    klass.find_by_param(param)
  end
end
