# 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',
        'modood',
        '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
