# typed: false
class GlobalStatesController < ApplicationController
  before_action :set_global_state, only: %i[edit update destroy]
  after_action :verify_authorized

  FA_COOKIE_KEYS = %w[
    furaffinity-cookie-a
    furaffinity-cookie-b
    furaffinity-cookie-oaid
  ].freeze

  IB_COOKIE_KEYS = %w[inkbunny-username inkbunny-password inkbunny-sid].freeze

  def index
    authorize GlobalState
    @global_states = policy_scope(GlobalState).order(:key)
  end

  def new
    @global_state = GlobalState.new
    authorize @global_state
  end

  def create
    @global_state = GlobalState.new(global_state_params)
    authorize @global_state
    if @global_state.save
      redirect_to global_states_path,
                  notice: "Global state was successfully created."
    else
      render :new, status: :unprocessable_entity
    end
  end

  def edit
    authorize @global_state
  end

  def update
    authorize @global_state
    if @global_state.update(global_state_params)
      redirect_to global_states_path,
                  notice: "Global state was successfully updated."
    else
      render :edit, status: :unprocessable_entity
    end
  end

  def destroy
    authorize @global_state
    @global_state.destroy
    redirect_to global_states_path,
                notice: "Global state was successfully deleted."
  end

  def fa_cookies
    authorize GlobalState
    @fa_cookies =
      FA_COOKIE_KEYS.map do |key|
        GlobalState.find_by(key: key) ||
          GlobalState.new(key: key, value_type: :string)
      end
  end

  def edit_fa_cookies
    authorize GlobalState
    @fa_cookies =
      FA_COOKIE_KEYS.map do |key|
        GlobalState.find_by(key: key) ||
          GlobalState.new(key: key, value_type: :string)
      end
  end

  def update_fa_cookies
    authorize GlobalState

    begin
      ActiveRecord::Base.transaction do
        fa_cookies_params.each do |key, value|
          state = GlobalState.find_or_initialize_by(key: key)
          state.value = value
          state.value_type = :string
          state.save!
        end
      end

      redirect_to fa_cookies_global_states_path,
                  notice: "FA cookies were successfully updated."
    rescue ActiveRecord::RecordInvalid => e
      @fa_cookies =
        FA_COOKIE_KEYS.map do |key|
          GlobalState.find_by(key: key) ||
            GlobalState.new(key: key, value_type: :string)
        end
      flash.now[:alert] = "Error updating FA cookies: #{e.message}"
      render :edit_fa_cookies, status: :unprocessable_entity
    end
  end

  def ib_cookies
    authorize GlobalState
    @ib_cookies =
      IB_COOKIE_KEYS.map do |key|
        GlobalState.find_by(key: key) ||
          GlobalState.new(key: key, value_type: :string)
      end
  end

  def edit_ib_cookies
    authorize GlobalState
    @ib_cookies =
      IB_COOKIE_KEYS
        .reject { |key| key == "inkbunny-sid" }
        .map do |key|
          GlobalState.find_by(key: key) ||
            GlobalState.new(key: key, value_type: :string)
        end
    @ib_sid = GlobalState.find_by(key: "inkbunny-sid")
  end

  def update_ib_cookies
    authorize GlobalState

    begin
      params_hash = params.require(:ib_cookies).permit(*IB_COOKIE_KEYS).to_h
      has_credentials =
        params_hash["inkbunny-username"].present? ||
          params_hash["inkbunny-password"].present?
      has_sid = params_hash["inkbunny-sid"].present?

      if has_credentials && has_sid
        raise ArgumentError,
              "Cannot set both credentials and session ID at the same time"
      end

      if !has_credentials && !has_sid
        raise ArgumentError, "Must set either credentials or session ID"
      end

      ActiveRecord::Base.transaction do
        if has_credentials
          # Update username and password
          %w[inkbunny-username inkbunny-password].each do |key|
            state = GlobalState.find_or_initialize_by(key: key)
            state.value = params_hash[key]
            state.value_type = :string
            state.save!
          end
        else
          # Update SID
          state = GlobalState.find_or_initialize_by(key: "inkbunny-sid")
          state.value = params_hash["inkbunny-sid"]
          state.value_type = :string
          state.save!
        end
      end

      redirect_to ib_cookies_global_states_path,
                  notice: "Inkbunny credentials were successfully updated."
    rescue ArgumentError => e
      @ib_cookies =
        IB_COOKIE_KEYS
          .reject { |key| key == "inkbunny-sid" }
          .map do |key|
            GlobalState.find_by(key: key) ||
              GlobalState.new(key: key, value_type: :string)
          end
      @ib_sid = GlobalState.find_by(key: "inkbunny-sid")
      flash.now[:alert] = "Error updating Inkbunny credentials: #{e.message}"
      render :edit_ib_cookies, status: :unprocessable_entity
    rescue ActiveRecord::RecordInvalid => e
      @ib_cookies =
        IB_COOKIE_KEYS
          .reject { |key| key == "inkbunny-sid" }
          .map do |key|
            GlobalState.find_by(key: key) ||
              GlobalState.new(key: key, value_type: :string)
          end
      @ib_sid = GlobalState.find_by(key: "inkbunny-sid")
      flash.now[:alert] = "Error updating Inkbunny credentials: #{e.message}"
      render :edit_ib_cookies, status: :unprocessable_entity
    end
  end

  private

  def set_global_state
    @global_state = GlobalState.find(params[:id])
  end

  def global_state_params
    params.require(:global_state).permit(:key, :value, :value_type)
  end

  def fa_cookies_params
    params.require(:fa_cookies).permit(*FA_COOKIE_KEYS)
  end

  def ib_cookies_params
    params.require(:ib_cookies).permit(
      *IB_COOKIE_KEYS.reject { |key| key == "inkbunny-sid" },
    )
  end
end
