# frozen_string_literal: true

# == Schema Information
#
# Table name: articles
#
#  id               :bigint           not null, primary key
#  backtrack_link   :string(191)
#  body             :text(65535)
#  comments_count   :integer          default(0)
#  diagnostic_steps :text(65535)
#  impact           :integer          default("no")
#  issue            :text(65535)
#  lang             :integer          default("english"), not null
#  root_cause       :text(65535)
#  solution         :text(65535)
#  status           :integer          default(0)
#  tags_count       :integer          default(0)
#  title            :string(191)
#  usefuls_count    :integer          default(0)
#  verified_status  :integer          default("verified")
#  created_at       :datetime         not null
#  updated_at       :datetime         not null
#  deleted_by_id    :bigint
#  user_id          :bigint
#
class Article < ApplicationRecord
  belongs_to :user, counter_cache: true, touch: true

  has_many :comments

  has_many :taggings, dependent: :destroy
  has_many :tags, through: :taggings

  has_many :article_products, dependent: :destroy
  has_many :products, through: :article_products, source: "product"

  has_many :article_components, dependent: :destroy
  has_many :components, through: :article_components, source: "component"

  has_many :article_categories, dependent: :destroy
  has_many :categories, through: :article_categories, source: "category"

  has_many :article_versions, dependent: :destroy
  has_many :versions, through: :article_versions, source: "version"

  has_many :article_reviewers, dependent: :destroy
  has_many :reviewers, through: :article_reviewers, source: "reviewer"

  has_many :inboxes
  has_many :usefuls
  has_many :useful_users, through: :usefuls, source: "user"

  belongs_to :deleted_by, optional: true, class_name: "User"
  belongs_to :approved_by, optional: true, class_name: "User"

  scope :current_day, -> { where(created_at: (Time.now.beginning_of_day..Time.now.end_of_day)) }
  scope :current_week, -> { where(created_at: (Time.now.beginning_of_week..Time.now.end_of_week)) }
  scope :current_month, -> { where(created_at: (Time.now.beginning_of_month..Time.now.end_of_month)) }

  after_commit do 
    EswJob.perform_later(self.id)
  end

  validates :title, presence: true
  extend Pagy::Search

  enum impact: { no: 0, low: 1, medium: 2, high: 3, critical: 4, catastrophic: 5 }
  enum verified_status: { verified: 0, unverified: 1, deleted: 2 }

  enum lang: {
    english: 0,
    chinese: 1,
  }

  searchkick language: "chinese", merge_mappings: true, mappings: {
    properties: {
      created_at: { type: "date" }
    }
  }

  def esw_data
    {
      id: id,
      title: title,
      body: issue_description,
      author: user&.username,
      url: "https://kb-old.pingcap.net/articles/#{id}",
      created_at: created_at,
      components: component_names,
      versions: version_names, 
      tags: tag_names,
      categories: category_names,
      issue: issue,
      solution: solution,
      root_cause: root_cause,
      verified_status: verified_status,
      impact: impact,
      diagnostic_steps: diagnostic_steps
    }
  end

  def search_data
    as_json(only: [:id,
        :issue,
        :solution,
        :root_cause,
        :diagnostic_steps,
        :verified_status,
        :impact,
        :user_id,
        :created_at,
        :updated_at
      ]
    ).merge(
      titile: title.to_s.gsub(".", " "),
      tag_names: tag_names,
      product_names: product_names,
      category_names: category_names,
      tag_ids: tag_ids,
      product_ids: product_ids,
      component_ids: component_ids,
      category_ids: category_ids,
      version_ids: version_ids
    )
  end

  def should_index?
    !deleted?
  end

  def issue_description
    issue.to_s[0, 300]
  end

  def images
    []
  end

  def issue_md
    filter = HTML::Pipeline::MarkdownFilter.new(issue.to_s)
    filter.call
  end

  def root_cause_md
    filter = HTML::Pipeline::MarkdownFilter.new(root_cause.to_s)
    filter.call
  end

  def diagnostic_steps_md
    filter = HTML::Pipeline::MarkdownFilter.new(diagnostic_steps.to_s)
    filter.call
  end

  def solution_md
    filter = HTML::Pipeline::MarkdownFilter.new(solution.to_s)
    filter.call
  end

  def tag_names
    tags.map { |x| x.name }.join(",")
  end

  def versions_affected
    versions.map { |x| x.name }.join(",")
  end

  def tag_names=(tag_names)
    return self.tags = [] if tag_names.blank?
    input_tag_names = JSON.parse(tag_names).map { |x| x["value"] }
    input_tags = input_tag_names.map { |x| Tag.create_with(user_id: self.user_id).find_or_create_by(name: x) }
    self.tags = input_tags
  end

  def product_names=(product_names)
    return self.products = [] if product_names.blank?
    input_p_names = JSON.parse(product_names).map { |x| x["value"] }
    input_products = input_p_names.map { |x| Product.find_by(name: x) }.compact
    self.products = input_products
  end

  def component_names=(component_names)
    return self.components = [] if component_names.blank?
    input_c_names = JSON.parse(component_names).map { |x| x["value"] }
    input_components = input_c_names.map { |x| Component.find_by(name: x) }.compact
    self.components = input_components
  end

  def category_names=(category_names)
    return self.categories = [] if category_names.blank?
    input_category_names = JSON.parse(category_names).map { |x| x["value"] }
    input_categories = input_category_names.map { |x| Category.find_by(name: x) }.compact
    self.categories = input_categories
  end

  def versions_affected=(version_names)
    return self.versions = [] if version_names.blank?
    input_version_names = JSON.parse(version_names).map { |x| x["value"] }
    input_versions = input_version_names.map { |x| Version.find_by(name: x) }.compact
    self.versions = input_versions
  end

  def product_names
    products.map { |x| x.name }.join(",")
  end

  def component_names
    components.map { |x| x.name }.join(",")
  end

  def category_names
    categories.map { |x| x.name }.join(",")
  end

  def version_names
    versions.map { |x| x.name }.join(",")
  end
end
