# frozen_string_literal: true

module SiteAdmin
  # PropsController
  # Manages properties for the current website
  # Uses Pwb::ListedProperty (materialized view) for reads and Pwb::RealtyAsset for writes
  class PropsController < SiteAdminController
    before_action :set_property, only: [:show]
    before_action :set_realty_asset, only: [
      :edit_general, :edit_text, :edit_sale_rental, :edit_location,
      :edit_labels, :edit_photos, :upload_photos, :remove_photo,
      :reorder_photos, :update_photo_alt, :update
    ]

    def index
      # Use Pwb::ListedProperty (materialized view) for listing - it's optimized for reads
      # Scope to current website and eager load prop_photos to avoid N+1 queries
      props = Pwb::ListedProperty
              .with_eager_loading
              .where(website_id: current_website&.id)
              .order(created_at: :desc)

      if params[:search].present?
        props = props.where(
          'reference ILIKE ? OR title ILIKE ? OR street_address ILIKE ? OR city ILIKE ?',
          "%#{params[:search]}%",
          "%#{params[:search]}%",
          "%#{params[:search]}%",
          "%#{params[:search]}%"
        )
      end

      @pagy, @props = pagy(props, limit: 25)
    end

    def new
      @prop = Pwb::RealtyAsset.new(website: current_website)
    end

    def create
      @prop = Pwb::RealtyAsset.new(new_prop_params)
      @prop.website = current_website

      if @prop.save
        redirect_to edit_general_site_admin_prop_path(@prop),
                    notice: 'Property created successfully. Now add more details.'
      else
        render :new, status: :unprocessable_entity
      end
    end

    def show
      # @prop set by before_action (uses Property view)
      # Pre-load all FieldKeys needed for display to avoid N+1 queries (tenant-scoped)
      feature_keys = @prop.features.map(&:feature_key).compact
      all_keys = [feature_keys, @prop.prop_type_key, @prop.prop_state_key].flatten.compact.uniq
      @field_keys_by_key = PwbTenant::FieldKey.where(global_key: all_keys).index_by(&:global_key)
    end

    def edit_general
      render :edit_general
    end

    def edit_text
      # Load listings for text editing - titles/descriptions are on listings now
      @sale_listing = @prop.sale_listings.first
      @rental_listing = @prop.rental_listings.first
      render :edit_text
    end

    def edit_sale_rental
      # Load associated listings for editing
      @sale_listing = @prop.sale_listings.first_or_initialize
      @rental_listing = @prop.rental_listings.first_or_initialize
      render :edit_sale_rental
    end

    def edit_location
      render :edit_location
    end

    def edit_labels
      # Load available labels from FieldKey organized by category
      # Uses Pwb::Config for centralized category definitions
      @label_categories = Pwb::Config::FIELD_KEY_CATEGORIES.transform_values do |info|
        { title: info[:short_title], description: info[:short_description] }
      end

      # Load field keys for each category (tenant-scoped)
      @labels_by_category = {}
      @label_categories.each_key do |tag|
        @labels_by_category[tag] = PwbTenant::FieldKey.where(tag: tag).visible.order(:sort_order).pluck(:global_key)
      end

      # Get current labels for this property
      @current_features = @prop.features.pluck(:feature_key)

      render :edit_labels
    end

    def edit_photos
      render :edit_photos
    end

    def upload_photos
      # Handle external URLs when in external image mode
      if params[:external_urls].present? && current_website&.external_image_mode
        urls = params[:external_urls].to_s.split("\n").map(&:strip).reject(&:blank?)
        if urls.any?
          max_sort_order = @prop.prop_photos.maximum(:sort_order) || 0
          created_count = 0
          urls.each_with_index do |url, index|
            prop_photo = @prop.prop_photos.build(
              sort_order: max_sort_order + index + 1,
              external_url: url
            )
            if prop_photo.save
              created_count += 1
            end
          end
          if created_count > 0
            redirect_to edit_photos_site_admin_prop_path(@prop), notice: "#{created_count} photo(s) added from URLs."
          else
            redirect_to edit_photos_site_admin_prop_path(@prop), alert: 'Failed to add photos. Please check the URLs.'
          end
          return
        end
      end

      # Handle file uploads (normal mode)
      if params[:photos].present?
        max_sort_order = @prop.prop_photos.maximum(:sort_order) || 0
        params[:photos].each_with_index do |photo, index|
          prop_photo = @prop.prop_photos.build(sort_order: max_sort_order + index + 1)
          prop_photo.image.attach(photo)
          prop_photo.save
        end
        redirect_to edit_photos_site_admin_prop_path(@prop), notice: "#{params[:photos].count} photo(s) uploaded successfully."
      else
        redirect_to edit_photos_site_admin_prop_path(@prop), alert: 'No photos selected.'
      end
    end

    def remove_photo
      photo = @prop.prop_photos.find(params[:photo_id])

      if photo.destroy
        redirect_to edit_photos_site_admin_prop_path(@prop), notice: 'Photo removed successfully.'
      else
        redirect_to edit_photos_site_admin_prop_path(@prop), alert: 'Failed to remove photo.'
      end
    end

    def reorder_photos
      if params[:photo_order].present?
        photo_ids = params[:photo_order].split(',')
        photo_ids.each_with_index do |photo_id, index|
          @prop.prop_photos.where(id: photo_id).update_all(sort_order: index + 1)
        end
        redirect_to edit_photos_site_admin_prop_path(@prop), notice: 'Photo order updated successfully.'
      else
        redirect_to edit_photos_site_admin_prop_path(@prop), alert: 'No order specified.'
      end
    end

    def update_photo_alt
      photo = @prop.prop_photos.find(params[:photo_id])
      if photo.update(description: params[:description])
        respond_to do |format|
          format.html { redirect_to edit_photos_site_admin_prop_path(@prop), notice: 'Alt text updated successfully.' }
          format.json { render json: { success: true, description: photo.description } }
        end
      else
        respond_to do |format|
          format.html { redirect_to edit_photos_site_admin_prop_path(@prop), alert: 'Failed to update alt text.' }
          format.json { render json: { success: false, errors: photo.errors.full_messages }, status: :unprocessable_entity }
        end
      end
    end

    def update
      ActiveRecord::Base.transaction do
        # Update the realty asset (physical property data)
        @prop.update!(asset_params) if asset_params.present?

        # Update or create sale listing if sale params present
        if sale_listing_params.present?
          sale_listing = @prop.sale_listings.first_or_initialize
          sale_listing.update!(sale_listing_params)
        end

        # Update or create rental listing if rental params present
        if rental_listing_params.present?
          rental_listing = @prop.rental_listings.first_or_initialize
          rental_listing.update!(rental_listing_params)
        end

        # Update features if features params present
        if params[:features].present?
          update_features(params[:features])
        end
      end

      redirect_to site_admin_prop_path(@prop), notice: 'Property was successfully updated.'
    rescue ActiveRecord::RecordInvalid => e
      redirect_to edit_general_site_admin_prop_path(@prop), alert: "Failed to update property: #{e.message}"
    end

    private

    def set_property
      # Use Property view for read-only show action
      # Scope to current website for security
      @prop = Pwb::ListedProperty.where(website_id: current_website&.id).find(params[:id])
    end

    def set_realty_asset
      # Use RealtyAsset for write operations
      # Scope to current website for security
      @prop = Pwb::RealtyAsset.where(website_id: current_website&.id).find(params[:id])
    end

    def new_prop_params
      params.require(:pwb_realty_asset).permit(
        :reference, :prop_type_key,
        :count_bedrooms, :count_bathrooms,
        :street_address, :city, :region, :postal_code, :country
      )
    end

    def asset_params
      return {} unless params[:pwb_realty_asset].present? || params[:pwb_prop].present?

      param_key = params[:pwb_realty_asset].present? ? :pwb_realty_asset : :pwb_prop
      params.require(param_key).permit(
        :reference,
        :count_bedrooms, :count_bathrooms, :count_garages, :count_toilets,
        :plot_area, :constructed_area, :year_construction,
        :energy_rating, :energy_performance,
        :street_number, :street_name, :street_address, :postal_code,
        :city, :region, :country, :latitude, :longitude,
        :prop_type_key, :prop_state_key, :prop_origin_key
      )
    end

    def sale_listing_params
      return {} unless params[:sale_listing].present?

      # Include title/description/seo_title/meta_description for each supported locale
      locale_fields = I18n.available_locales.flat_map do |locale|
        [
          "title_#{locale}".to_sym,
          "description_#{locale}".to_sym,
          "seo_title_#{locale}".to_sym,
          "meta_description_#{locale}".to_sym
        ]
      end

      params.require(:sale_listing).permit(
        :visible, :highlighted, :archived, :reserved, :furnished,
        :price_sale_current_cents, :price_sale_current_currency,
        :commission_cents, :commission_currency,
        *locale_fields
      )
    end

    def rental_listing_params
      return {} unless params[:rental_listing].present?

      # Include title/description/seo_title/meta_description for each supported locale
      locale_fields = I18n.available_locales.flat_map do |locale|
        [
          "title_#{locale}".to_sym,
          "description_#{locale}".to_sym,
          "seo_title_#{locale}".to_sym,
          "meta_description_#{locale}".to_sym
        ]
      end

      params.require(:rental_listing).permit(
        :visible, :highlighted, :archived, :reserved, :furnished,
        :for_rent_short_term, :for_rent_long_term,
        :price_rental_monthly_current_cents, :price_rental_monthly_current_currency,
        :price_rental_monthly_low_season_cents, :price_rental_monthly_high_season_cents,
        *locale_fields
      )
    end

    def update_features(features_param)
      # features_param is an array of selected feature keys
      selected_features = Array(features_param)

      # Remove features that are no longer selected
      @prop.features.where.not(feature_key: selected_features).destroy_all

      # Add new features
      selected_features.each do |feature_key|
        @prop.features.find_or_create_by(feature_key: feature_key)
      end
    end
  end
end
