class City < ApplicationRecord
  extend FriendlyId
  friendly_id :slug_candidates, use: :slugged
  belongs_to :country, optional: true
  belongs_to :state, optional: true

  has_many :weather_arts, dependent: :destroy

  has_many :visits, class_name: "Ahoy::Visit", foreign_key: :city_id
  has_many :events, class_name: "Ahoy::Event", foreign_key: :city_id

  delegate :region, to: :country

  validates :name, presence: true
  validates :latitude, presence: true
  validates :longitude, presence: true

  delegate :region, to: :country

  scope :by_region, ->(region_id) { joins(:country).where(countries: { region_id: region_id }) }
  scope :by_country, ->(country_id) { where(country_id: country_id) }
  scope :active, -> { where(active: true) }
  scope :inactive, -> { where(active: false) }

  # 在 City 模型中
  scope :by_popularity, ->(period = :year, limit = 100) {
    # 根据时间周期确定时间范围
    start_time =
      case period.to_sym
      when :day
        1.day.ago
      when :week
        1.week.ago
      when :month
        1.month.ago
      when :year
        1.year.ago
      else
        1.year.ago
      end

    # 根据数据库类型构建不同的查询
    base_query = if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
                   joins(<<-SQL.squish)
      LEFT JOIN ahoy_events ON#{' '}
        json_extract(ahoy_events.properties, '$.city_id') = cities.id
        AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view'
        AND ahoy_events.time > '#{start_time}'
    SQL
    else
                   joins(<<-SQL.squish)
      LEFT JOIN ahoy_events ON#{' '}
        (ahoy_events.properties::jsonb->>'city_id')::integer = cities.id
        AND ahoy_events.properties::jsonb->>'event_type' = 'city_view'
        AND ahoy_events.time > '#{start_time}'
    SQL
    end

    base_query
      .group("cities.id")
      .select("cities.*, COUNT(ahoy_events.id) as visit_count")
      .order("visit_count DESC")
      .limit(limit)
  }

  scope :least_popular_active, ->(limit = 100) {
    if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
      active
        .joins("LEFT JOIN ahoy_events ON json_extract(ahoy_events.properties, '$.city_id') = cities.id
               AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view'")
        .group("cities.id")
        .select("cities.*, COUNT(ahoy_events.id) as visit_count")
        .order("visit_count ASC, cities.name ASC").limit(limit)
    else
      active
        .joins("LEFT JOIN ahoy_events ON (ahoy_events.properties::jsonb->>'city_id')::integer = cities.id
               AND ahoy_events.properties::jsonb->>'event_type' = 'city_view'")
        .group("cities.id")
        .select("cities.*, COUNT(ahoy_events.id) as visit_count")
        .order("visit_count ASC, cities.name ASC").limit(limit)
    end
  }
  scope :most_popular_inactive, ->(limit = 100) {
    if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
      where(active: false)
        .joins("LEFT JOIN ahoy_events ON json_extract(ahoy_events.properties, '$.city_id') = cities.id
               AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view'")
        .group("cities.id")
        .select("cities.*, COUNT(ahoy_events.id) as visit_count")
        .order("COUNT(ahoy_events.id) DESC, cities.name ASC").limit(limit)
    else
      where(active: false)
        .joins("LEFT JOIN ahoy_events ON (ahoy_events.properties::jsonb->>'city_id')::integer = cities.id
               AND ahoy_events.properties::jsonb->>'event_type' = 'city_view'")
        .group("cities.id")
        .select("cities.*, COUNT(ahoy_events.id) as visit_count")
        .order("COUNT(ahoy_events.id) DESC, cities.name ASC").limit(limit)
    end
  }
  scope :search_by_name, ->(query) {
    return all if query.blank?

    decoded_query = URI.decode_www_form_component(query).downcase

    where(
      "LOWER(cities.name) LIKE :query", query: "%#{decoded_query}%"
    )
  }

  # 定义 latest_weather_art 关联
  has_one :latest_weather_art, -> { order(weather_date: :desc) },
          class_name: "WeatherArt"

  # 包含最新天气艺术的 scope
  scope :with_latest_weather_art, -> {
    includes(:latest_weather_art)
  }

  # 只获取有最新天气艺术的城市
  scope :has_weather_art, -> {
    joins(:weather_arts).distinct
  }

  # 按最新天气更新时间排序
  scope :order_by_latest_weather, -> {
    joins(:weather_arts)
      .group("cities.id")
      .order("MAX(weather_arts.weather_date) DESC")
  }

  # 获取最近24小时内更新过天气的城市
  scope :recently_updated, -> {
    joins(:weather_arts)
      .where("weather_arts.weather_date > ?", 24.hours.ago)
      .distinct
  }


  def to_s
    name
  end

  def slug_candidates
    [
      :name,
      [ :country, :name ]
    ]
  end

  def localized_name
    I18n.t("cities.#{name.parameterize.underscore}", default: name)
  end

  def full_name
    "#{name}, #{country}"
  end

  def should_generate_new_friendly_id?
    name_changed? || super
  end

  def self.ransackable_associations(auth_object = nil)
    [ "weather_arts" ]
  end

  def self.ransackable_attributes(auth_object = nil)
    [ "active", "country_id", "created_at", "id", "id_value", "last_image_generation", "last_weather_fetch", "latitude", "longitude", "name", "priority", "region", "slug", "timezone", "updated_at" ]
  end

  def last_weather_fetch
    # latest_weather_art&.created_at
    Rails.cache.fetch("city/#{id}/last_weather_fetch", expires_in: 1.hour) do
      latest_weather_art&.created_at
    end
  end

  def last_image_generation
    # latest_weather_art&.image&.created_at
    Rails.cache.fetch("city/#{id}/last_image_generation", expires_in: 1.hour) do
      latest_weather_art&.image&.created_at
    end
  end

  def latest_weather_art
    weather_arts.order(weather_date: :desc).first
  end

  def view_count(period = :day)
    start_time = case period
    when :day
                   1.day.ago
    when :week
                   7.days.ago
    when :month
                   1.month.ago
    when :year
                   1.year.ago
    else
                   1.year.ago
    end
    if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite"
      # Ahoy::Event.where("json_extract(properties, '$.event_type') = 'city_view' AND json_extract(properties, '$.city_id') = ?", self.id).count
      Ahoy::Event
        .where("time >= ?", start_time)
        .where("json_extract(properties, '$.event_type') = 'city_view' AND json_extract(properties, '$.city_id') = ?",
               self.id)
        .count
    else
      # Ahoy::Event.where("properties::jsonb->>'event_type' = 'city_view' AND (properties::jsonb->>'city_id')::integer = ?", self.id).count
      Ahoy::Event
        .where("time >= ?", start_time)
        .where("properties::jsonb->>'event_type' = 'city_view' AND (properties::jsonb->>'city_id')::integer = ?",
                        self.id)
        .count
    end
  end

  def formatted_current_time(type = :date, use_local_timezone = true)
    # 获取时区
    timezone_info = self.country&.timezones.present? ?
                      JSON.parse(country.timezones)&.first :
                      { "zoneName" => "UTC", "gmtOffsetName" => "UTC+00:00" }

    # 设置时区对象
    time_zone = ActiveSupport::TimeZone[timezone_info["zoneName"]] ||
      ActiveSupport::TimeZone["UTC"]
    time = Time.current

    case type
    when :date
      # 格式化日期
      time.strftime("%B %d, %Y")
    when :time
      use_local_timezone ?
        "#{time.in_time_zone(time_zone).strftime('%H:%M')} #{timezone_info['gmtOffsetName']}" :
        "#{time.utc.strftime('%H:%M')} UTC"
    when :all
      # 返回日期 + 时间 + UTC 信息
      date = time.strftime("%B %d, %Y")
      time = use_local_timezone ?
               updated_at.in_time_zone(time_zone).strftime("%H:%M") + " #{timezone_info['gmtOffsetName']}" :
               updated_at.utc.strftime("%H:%M") + " UTC"
      "#{date} #{time}"
    else
      "Unknown #{type}"
    end
  end
end