require 'faraday'
require 'faraday_middleware'
require 'faraday-cookie_jar'

module UqamGradeNotification
  class Student
    attr_reader :code, :password

    def initialize args
      args = HashWithIndifferentAccess.new(args)
      @code = args.fetch("code")
      @password = args.fetch("password")
    end

    def grades
      @grades ||= semesters[0..1].map do |semester|
        courses = semester["programmes"][0]["activites"]
        courses.map do |course|
          get_results(course)
        end
      end
    end

    private

    def semesters
      @semesters ||= connection.get do |req|
        req.url "/apis/resumeResultat/identifiant"
        req.headers['Authorization'] = "Bearer #{token}"
      end.body["data"]["resultats"]
    end

    def connection
      Faraday.new(url: "https://portailetudiant.uqam.ca") do |c|
        c.request :json
        c.response :json, content_type: /\bjson$/
        c.use Faraday::Response::RaiseError
        c.use :cookie_jar
        c.adapter :net_http
      end
    end

    def get_results course
      data = connection.get do |req|
        req.url "/apis/resultatActivite/identifiant/#{course['trimestre']}/#{course['sigle']}/#{course['groupe']}"
        req.headers['Authorization'] = "Bearer #{token}"
      end.body["data"]["resultats"][0]["programmes"][0]["activites"][0]

      {
        "name" => data["titreActivite"],
        "note" => data["note"],
        "evaluations" => data["evaluations"]
      }
    end

    def informations
      @informations ||= connection.get do |req|
        req.url "/apis/resume/identifiant"
        req.headers['Authorization'] = "Bearer #{token}"
      end.body["data"]["resume"]
    end

    def token
      @token ||= get_token
    end

    def get_token
      connection.post do |req|
        req.url "/authentification"
        req.headers['Content-Type'] = 'application/json;charset=UTF-8'
        req.headers['Origin'] = 'https://portailetudiant.uqam.ca'
        req.headers['Referer'] = 'https://portailetudiant.uqam.ca'
        req.body = {identifiant: code, motDePasse: password}
      end.body["token"]
    end
  end
end
