require_dependency "panda_pal/application_controller"

module PandaPal
  class LtiV1P3Controller < ApplicationController
    skip_before_action :verify_authenticity_token

    before_action :validate_launch!, only: [:resource_link_request]
    around_action :switch_tenant, only: [:resource_link_request]

    def login
      current_session_data[:lti_oauth_nonce] = SecureRandom.uuid

      @form_action = current_lti_platform.authentication_redirect_url
      @method = :post
      @form_data = {
        scope: 'openid',
        response_type: 'id_token',
        response_mode: 'form_post',
        prompt: 'none',
        redirect_uri: params[:target_link_uri] || v1p3_resource_link_request_url,
        client_id: params.require(:client_id),
        login_hint: params.require(:login_hint),
        lti_message_hint: params.require(:lti_message_hint),
        state: current_session.session_key,
        nonce: current_session_data[:lti_oauth_nonce]
      }
    end

    def resource_link_request
      # Redirect to correct region/env?
      if params[:launch_type]
        current_session_data.merge!({
          lti_version: 'v1p3',
          lti_launch_placement: params[:launch_type],
          launch_params: @decoded_lti_jwt,
        })

        redirect_with_session_to(:"#{LaunchUrlHelpers.launch_route(params[:launch_type])}_url", route_context: main_app)
      end
    end

    def tool_config
      if PandaPal.lti_environments.empty?
        render plain: 'Domains must be set in lti_environments'
        return
      end

      platform = PandaPal.lti_options.delete(:platform) || 'canvas.instructure.com'
      request_url = "#{request.scheme}://#{request.host_with_port}"
      parsed_request_url = URI.parse(request_url)

      mapped_placements = PandaPal.lti_paths.map do |k, opts|
        opts = opts.dup
        opts.delete(:route_helper_key)
        opts.merge!({
          placement: k,
          target_link_uri: LaunchUrlHelpers.absolute_launch_url(k.to_sym, host: parsed_request_url, launch_handler: v1p3_resource_link_request_path),
        })
        opts
      end

      config_json = {
        title: PandaPal.lti_options[:title],
        scopes: [],
        public_jwk_url: v1p3_public_jwks_url,
        description: PandaPal.lti_options[:description] || 'PandaPal LTI',
        target_link_uri: v1p3_resource_link_request_url, #app_url(:resource_link_request, request),
        oidc_initiation_url: v1p3_oidc_login_url,
        extensions: [{
          platform: platform,
          privacy_level: "public",
          settings: {
            placements: mapped_placements,
            environments: PandaPal.lti_environments,
          },
        }],
        custom_fields: PandaPal.lti_custom_params, # PandaPal.lti_options[:custom_fields],
      }

      render json: config_json
    end

    def public_jwks
      render json: {
        keys: [JWT::JWK.new(PandaPal.lti_private_key).export]
      }
    end

    private

    def auth_redirect_query
      return unless params[:target_link_uri]&.include? 'platform_redirect_url='

      platform_redirect_url = Rack::Utils.parse_query(URI(params[:target_link_uri]).query)&.dig('platform_redirect_url')
      "?platform_redirect_url=#{platform_redirect_url}"
    end
  end
end