# frozen_string_literal: true

namespace :china_regions do

desc 'Download and import regions into tables'
task all: :environment do
  Rake::Task['china_regions:download'].invoke
  Rake::Task['china_regions:import'].invoke
end

desc 'Download regions from `Administrative-divisions-of-China`'
task download: :environment do
  ChinaRegions::Download.all
end

desc 'Import provinces and cities and areas to database'
task import: :environment do
  ChinaRegions::Import.all
end

end

module ChinaRegions

module Download
  require "down"

  module_function

  def all(filename = 'pca-code.json')
    detect_folder

    downloading(filename)
  end

  def downloading(filename)
    down(filename)

    move_to(filename)
  end

  def down(filename)
    Down.download(
      github_url(filename),
      destination: File.join(Rails.root, 'db', 'regions')
    )
  end

  def detect_folder
    FileUtils.mkdir_p File.join(Rails.root, 'db', 'regions')
  end

  def github_url(filename)
    [
      'https://raw.githubusercontent.com',
      'encoreshao',
      'Administrative-divisions-of-China',
      'master',
      'dist',
      filename
    ].join('/')
  end

  def move_to(filename)
    src_file = Dir.glob(File.join(Rails.root, 'db', 'regions', "*.json")).max_by { |f| File.mtime(f) }

    FileUtils.mv src_file, File.join(Rails.root, 'db', 'regions', filename)
  end
end

module Import
  require 'json'
  require 'ruby-pinyin'

  module_function

  def all(filename = 'pca-code.json')
    data_hash(filename).each { |province_hash| creating_province(province_hash) }

    puts "Imported done!"
    puts ''
    puts "  Total of #{Province.count} provinces."
    puts "  Total of #{City.count} cities."
    puts "  Total of #{District.count} districts."
  end

  def creating_province(prov_hash)
    province = Province.find_or_create_by(name: prov_hash['name'])
    province.update(build_params(prov_hash['name'], prov_hash['code']))

    prov_hash["children"].each { |city_hash| creating_city(province, city_hash) }
  end

  def creating_city(province, city_hash)
    city = City.find_or_create_by(province: province, name: city_hash['name'])
    city_params = build_params(city_hash['name'], city_hash['code'])
                  .merge(city_level(city_hash['name']))
    city.update(city_params)

    city_hash['children'].each { |district| creating_district(city, district) }
  end

  def city_level(city_name)
    {
      level: municipalities.include?(city_name) ? 1 : 4
    }
  end

  def creating_district(city, district_hash)
    district = District.find_or_create_by(city: city, name: district_hash['name'])
    district.update(build_params(district_hash['name'], district_hash['code']))
  end

  def build_params(full_name, code)
    new_name      = convert_pinyin(to_decorate(full_name))
    name_en       = new_name.join
    name_abbr     = new_name.map { |e| e[0] }.join

    {
      code: code,
      name_en: name_en,
      name_abbr: name_abbr
    }
  end

  def convert_pinyin(text)
    PinYin.of_string(text)
  end

  def to_decorate(text)
    text.gsub(/市|自治州|地区|特别行政区|区|县|自治县/, '')
  end

  def municipalities
    %w[北京市 天津市 重庆市 上海市]
  end

  def data_hash(filename)
    @data_hash ||= JSON.parse File.read(latest_file_path(filename))
  end

  def latest_file_path(filename)
    File.join(Rails.root, 'db', 'regions', filename)
  end
end

end