class PendingDuplicateMergesController < ApplicationController
  before_action :set_transaction

  def new
    @limit = 10
    # Ensure offset is non-negative to prevent abuse
    @offset = [ (params[:offset] || 0).to_i, 0 ].max

    # Fetch one extra to determine if there are more results
    candidates = @transaction.pending_duplicate_candidates(limit: @limit + 1, offset: @offset).to_a
    @has_more = candidates.size > @limit
    @potential_duplicates = candidates.first(@limit)

    # Calculate range for display (e.g., "1-10", "11-20")
    @range_start = @offset + 1
    @range_end = @offset + @potential_duplicates.count
  end

  def create
    return unless require_account_permission!(@transaction.entry.account, :annotate, redirect_path: transactions_path)

    # Manually merge the pending transaction with the selected posted transaction
    unless merge_params[:posted_entry_id].present?
      redirect_back_or_to transactions_path, alert: "Please select a posted transaction to merge with"
      return
    end

    # Validate the posted entry is an eligible candidate (same account, currency, not pending)
    posted_entry = find_eligible_posted_entry(merge_params[:posted_entry_id])

    unless posted_entry
      redirect_back_or_to transactions_path, alert: "Invalid transaction selected for merge"
      return
    end

    # Store the merge suggestion and immediately execute it
    @transaction.update!(
      extra: (@transaction.extra || {}).merge(
        "potential_posted_match" => {
          "entry_id" => posted_entry.id,
          "reason" => "manual_match",
          "posted_amount" => posted_entry.amount.to_s,
          "confidence" => "high",  # Manual matches are high confidence
          "detected_at" => Date.current.to_s
        }
      )
    )

    # Immediately merge
    if @transaction.merge_with_duplicate!
      redirect_back_or_to transactions_path, notice: "Pending transaction merged with posted transaction"
    else
      redirect_back_or_to transactions_path, alert: "Could not merge transactions"
    end
  end

  private
    def set_transaction
      entry = Current.accessible_entries.find(params[:transaction_id])
      @transaction = entry.entryable

      unless @transaction.is_a?(Transaction) && @transaction.pending?
        redirect_to transactions_path, alert: "This feature is only available for pending transactions"
      end
    end

    def find_eligible_posted_entry(entry_id)
      # Constrain to same account, currency, and ensure it's a posted transaction
      # Use the same logic as pending_duplicate_candidates to ensure consistency
      conditions = Transaction::PENDING_PROVIDERS.map { |provider| "(transactions.extra -> '#{provider}' ->> 'pending')::boolean IS NOT TRUE" }

      @transaction.entry.account.entries
        .joins("INNER JOIN transactions ON transactions.id = entries.entryable_id AND entries.entryable_type = 'Transaction'")
        .where(id: entry_id)
        .where(currency: @transaction.entry.currency)
        .where.not(id: @transaction.entry.id)
        .where(conditions.join(" AND "))
        .first
    end

    def merge_params
      params.require(:pending_duplicate_merges).permit(:posted_entry_id)
    end
end
