class MaterialsController < ApplicationController
  def index
    page = (params[:page].presence || 1).to_i
    limit = (params[:limit].presence || 20).to_i

    page = 1 if page < 1
    limit = 1 if limit < 1

    offset = (page - 1) * limit

    tag_id = params[:tag_id].presence
    parent_id = params[:parent_id].presence

    q = Material.includes(:tag, :created_by_user).with_attached_file
    q = q.where(tag_id:) if tag_id
    q = q.where(parent_id:) if parent_id

    count = q.count
    materials = q.order(created_at: :desc, id: :desc).limit(limit).offset(offset)

    render json: { materials: MaterialRepr.many(materials, host: request.base_url), count: count }
  end

  def show
    material =
        Material
        .includes(:tag)
        .with_attached_file
        .find_by(id: params[:id])
    return head :not_found unless material

    wiki_page_body = material.tag.tag_name.wiki_page&.current_revision&.body

    render json: MaterialRepr.base(material, host: request.base_url).merge(wiki_page_body:)
  end

  def create
    return head :unauthorized unless current_user

    tag_name_raw = params[:tag].to_s.strip
    file = params[:file]
    url = params[:url].to_s.strip.presence
    return render_unprocessable_entity('タグは必須です．', field: :tag) if tag_name_raw.blank?
    if file.blank? && url.blank?
      return render_validation_error fields: { file: ['ファイルまたは URL は必須です．'],
                                               url: ['ファイルまたは URL は必須です．'] }
    end

    tag_name = TagName.find_undiscard_or_create_by!(name: tag_name_raw)
    tag = tag_name.tag
    tag = Tag.create!(tag_name:, category: :material) unless tag

    material = Material.new(tag:, url:,
                            created_by_user: current_user,
                            updated_by_user: current_user)
    material.file.attach(file)

    if material.save
      render json: MaterialRepr.base(material, host: request.base_url), status: :created
    else
      render_validation_error material
    end
  end

  def update
    return head :unauthorized unless current_user
    return head :forbidden unless current_user.gte_member?

    material = Material.with_attached_file.find_by(id: params[:id])
    return head :not_found unless material

    tag_name_raw = params[:tag].to_s.strip
    file = params[:file]
    url = params[:url].to_s.strip.presence
    return render_unprocessable_entity('タグは必須です．', field: :tag) if tag_name_raw.blank?
    if file.blank? && url.blank?
      return render_validation_error fields: { file: ['ファイルまたは URL は必須です．'],
                                               url: ['ファイルまたは URL は必須です．'] }
    end

    tag_name = TagName.find_undiscard_or_create_by!(name: tag_name_raw)
    tag = tag_name.tag
    tag = Tag.create!(tag_name:, category: :material) unless tag

    material.update!(tag:, url:, updated_by_user: current_user)
    if file
      material.file.attach(file)
    else
      material.file.purge
    end

    if material.save
      render json: MaterialRepr.base(material, host: request.base_url)
    else
      render_validation_error material
    end
  end

  def destroy
    return head :unauthorized unless current_user
    return head :forbidden unless current_user.gte_member?

    material = Material.find_by(id: params[:id])
    return head :not_found unless material

    material.discard
    head :no_content
  end
end
