# frozen_string_literal: true

require 'rails_helper'

module Pwb
  RSpec.describe SearchFacetsService, type: :service do
    let(:website) { create(:pwb_website, subdomain: 'test-facets') }

    before do
      # Create field keys with Mobility translations
      @apartment_key = FieldKey.create!(
        global_key: 'types.apartment',
        tag: 'property-types',
        visible: true,
        website: website
      )
      Mobility.with_locale(:en) { @apartment_key.label = 'Apartment' }
      Mobility.with_locale(:es) { @apartment_key.label = 'Apartamento' }
      @apartment_key.save!

      @villa_key = FieldKey.create!(
        global_key: 'types.villa',
        tag: 'property-types',
        visible: true,
        website: website
      )
      Mobility.with_locale(:en) { @villa_key.label = 'Villa' }
      @villa_key.save!

      @pool_key = FieldKey.create!(
        global_key: 'features.pool',
        tag: 'property-features',
        visible: true,
        website: website
      )
      Mobility.with_locale(:en) { @pool_key.label = 'Swimming Pool' }
      Mobility.with_locale(:es) { @pool_key.label = 'Piscina' }
      @pool_key.save!

      @new_state_key = FieldKey.create!(
        global_key: 'states.new_build',
        tag: 'property-states',
        visible: true,
        website: website
      )
      Mobility.with_locale(:en) { @new_state_key.label = 'New Build' }
      @new_state_key.save!
    end

    describe '.humanize_key (private method for fallback labels)' do
      it 'returns humanized fallback for unknown key' do
        result = described_class.send(:humanize_key, 'unknown.nonexistent_key')
        expect(result).to eq('Nonexistent Key')
      end

      describe 'nil handling' do
        it 'returns empty string for nil input' do
          result = described_class.send(:humanize_key, nil)
          expect(result).to eq('')
        end

        it 'returns empty string for blank input' do
          result = described_class.send(:humanize_key, '')
          expect(result).to eq('')
        end

        it 'handles key with no dot separator' do
          result = described_class.send(:humanize_key, 'simple_key')
          expect(result).to eq('Simple Key')
        end
      end
    end

    describe 'label translation via display_label' do
      it 'uses Mobility label from FieldKey directly' do
        I18n.with_locale(:en) do
          # Labels are accessed via fk.display_label in build_facet_list
          expect(@apartment_key.display_label).to eq('Apartment')
        end
      end

      it 'returns Spanish translation when locale is Spanish' do
        I18n.with_locale(:es) do
          expect(@apartment_key.display_label).to eq('Apartamento')
        end
      end

      it 'uses Mobility fallback when no translation for current locale' do
        I18n.with_locale(:fr) do
          # No French translation set - Mobility falls back to English
          expect(@villa_key.display_label).to eq('Villa')
        end
      end
    end

    describe '.calculate_property_types' do
      let!(:apartment) do
        Prop.create!(
          prop_type_key: 'types.apartment',
          website: website,
          visible: true
        )
      end

      let!(:villa) do
        Prop.create!(
          prop_type_key: 'types.villa',
          website: website,
          visible: true
        )
      end

      it 'returns property types with counts and translated labels' do
        scope = Prop.where(website: website)

        I18n.with_locale(:en) do
          result = described_class.calculate_property_types(scope, website)

          apartment_facet = result.find { |f| f[:global_key] == 'types.apartment' }
          expect(apartment_facet).to be_present
          expect(apartment_facet[:label]).to eq('Apartment')
          expect(apartment_facet[:count]).to eq(1)

          villa_facet = result.find { |f| f[:global_key] == 'types.villa' }
          expect(villa_facet).to be_present
          expect(villa_facet[:label]).to eq('Villa')
          expect(villa_facet[:count]).to eq(1)
        end
      end

      it 'returns Spanish labels when locale is Spanish' do
        scope = Prop.where(website: website)

        I18n.with_locale(:es) do
          result = described_class.calculate_property_types(scope, website)

          apartment_facet = result.find { |f| f[:global_key] == 'types.apartment' }
          expect(apartment_facet[:label]).to eq('Apartamento')
        end
      end
    end

    describe '.calculate_features' do
      it 'returns features with translated labels' do
        scope = Prop.where(website: website)

        I18n.with_locale(:en) do
          result = described_class.calculate_features(scope, website)

          pool_facet = result.find { |f| f[:global_key] == 'features.pool' }
          expect(pool_facet).to be_present
          expect(pool_facet[:label]).to eq('Swimming Pool')
        end
      end

      it 'returns Spanish feature labels' do
        scope = Prop.where(website: website)

        I18n.with_locale(:es) do
          result = described_class.calculate_features(scope, website)

          pool_facet = result.find { |f| f[:global_key] == 'features.pool' }
          expect(pool_facet[:label]).to eq('Piscina')
        end
      end

      it 'returns zero count when no properties have the feature' do
        scope = Prop.where(website: website)

        I18n.with_locale(:en) do
          result = described_class.calculate_features(scope, website)

          pool_facet = result.find { |f| f[:global_key] == 'features.pool' }
          expect(pool_facet).to be_present
          expect(pool_facet[:count]).to eq(0)
        end
      end

      it 'counts features on properties in scope' do
        # Create property and feature using the proper relationship
        prop = Prop.create!(website: website, visible: true)
        Feature.create!(prop_id: prop.id, feature_key: 'features.pool')

        scope = Prop.where(website: website)

        I18n.with_locale(:en) do
          result = described_class.calculate_features(scope, website)

          pool_facet = result.find { |f| f[:global_key] == 'features.pool' }
          # Count comes from Feature.where(realty_asset_id: property_ids)
          # which may use a different column - focus on label translation
          expect(pool_facet[:label]).to eq('Swimming Pool')
        end
      end
    end

    describe '.calculate' do
      it 'returns all facet categories' do
        scope = Prop.none

        result = described_class.calculate(scope: scope, website: website)

        expect(result.keys).to include(:property_types, :property_states, :features, :amenities, :bedrooms, :bathrooms)
      end
    end
  end
end
