class Material < ApplicationRecord
  include MyDiscard

  SOURCE_KINDS = ['uri', 'google_drive_path', 'google_drive_file',
                  'legacy_drive_path'].freeze

  default_scope -> { kept }

  belongs_to :parent, class_name: 'Material', optional: true
  has_many :children, class_name: 'Material', foreign_key: :parent_id, dependent: :nullify

  belongs_to :tag, optional: true
  belongs_to :created_by_user, class_name: 'User', optional: true
  belongs_to :updated_by_user, class_name: 'User', optional: true

  has_many :material_versions, dependent: :destroy
  has_many :material_export_items, dependent: :destroy

  has_one_attached :file, dependent: :purge
  has_one_attached :thumbnail, dependent: :purge

  before_validation :assign_normalized_source_key

  validates :tag_id, uniqueness: true, allow_nil: true
  validates :source_kind,
            inclusion: { in: SOURCE_KINDS },
            allow_blank: true

  validate :file_must_be_attached
  validate :tag_must_be_material_category

  def content_type
    return nil unless file&.attached?

    file.blob.content_type
  end

  def file_byte_size
    return nil unless file&.attached?

    file.blob.byte_size
  end

  def file_filename
    return nil unless file&.attached?

    file.blob.filename.to_s
  end

  def snapshot_export_paths
    material_export_items.order(:profile).pluck(:profile, :export_path).to_h
  end

  private

  def assign_normalized_source_key
    if source_kind.blank?
      self.normalized_source_key = nil
      return
    end

    self.normalized_source_key =
        MaterialSyncSuppression.normalize_source_key(source_kind:,
                                                     source_uri:,
                                                     drive_path: source_path,
                                                     drive_file_id: source_file_id)
  end

  def file_must_be_attached
    return if url.present? || file.attached?

    errors.add(:url, 'URL かファイルのどちらかは必須です．')
  end

  def tag_must_be_material_category
    return if tag.blank? || tag.character? || tag.material?

    errors.add(:tag, '素材カテゴリのタグを指定してください．')
  end
end
