class EdFi::Wisconsin::ApplicationService
  def self.call(*args, &block)
    service = new(*args, &block)
    service.destroy_logs
    service.call
  end

  def initialize(school_year_id, params={})
    @school_year_id = school_year_id
    @params = params
    set_time_zone
  end

  def valid_token?(credentials=nil)
    access_token(credentials).present?
  end

  def destroy_all
    response = JSON.parse(RestClient.get(url, headers))
    ids = response.map { |r| r['id'] }
    ids.each { |i| RestClient.delete("#{url}/#{i}", headers) }
  end

  def destroy_logs
    school_year.ed_fi_logs.where(endpoint: endpoint).delete_all
  end

  def edfi_school?
    return if state_id.blank?

    RestClient.get("#{api_url}/schools?schoolId=#{state_id.number}", headers)
  rescue
    false
  end

  private
    def set_time_zone
      Time.zone = school.time_zone
    end

    def base_url(credentials = nil)
      secrets = Rails.application.secrets.edfi[:wisconsin]
      year = credentials_academic_year(credentials)

      if year > 2025
        secrets[:v7_base_url]
      elsif year > 2023
        secrets[:v6_base_url]
      else
        secrets[:base_url]
      end
    end

    def api_url(credentials = nil)
      year = credentials_academic_year(credentials)

      if year > 2025
        "#{base_url(credentials)}/#{year}/data/v3/ed-fi"
      else
        "#{base_url(credentials)}/data/v3/#{year}/ed-fi"
      end
    end

    def url
      "#{api_url}/#{endpoint}"
    end

    def school_year
      @school_year ||= SchoolYear.find(@school_year_id)
    end

    def school
      @school ||= school_year.school
    end

    def state_id
      @state_id ||= school.state_id
    end

    def local_education_agency_id
      edfi_school['localEducationAgencyReference']['localEducationAgencyId']
    end

    def reporting_config
      @reporting_config ||= school_year.state_reporting_config
    end

    def school_config
      @school_config ||= school.school_config
    end

    def credentials_academic_year(credentials)
      credentials&.fetch('academic_year', nil) || school_year.academic_year
    end

    def credential
      @credential ||= EdFi::Credential.find_or_initialize_by(school: school, academic_year: school_year.academic_year)
    end

    def access_token(credentials=nil)
      @access_token ||= request_token(credentials)['access_token'] if request_token(credentials)
    end

    def request_token(credentials=nil)
      body = {
        client_id: credentials&.fetch('key', nil) || credential.key,
        client_secret: credentials&.fetch('secret', nil) || credential.secret,
        grant_type: :client_credentials
      }

      resp = begin
        if credentials_academic_year(credentials) > 2025
          RestClient.post("#{base_url(credentials)}/#{credentials_academic_year(credentials)}/oauth/token", body)
        else
          RestClient.post("#{base_url(credentials)}/oauth/token", body)
        end
      rescue RestClient::Exception => e
        false
      end
      JSON.parse(resp) if resp
    end

    def headers
      { Authorization: "Bearer #{access_token}", 'Content-Type' => 'application/json' }
    end

    def rest_client_request(method, path, model, body: {})
      RestClient::Request.execute(
        method: method,
        url: path,
        headers: headers,
        payload: body
      )
    rescue RestClient::Exception => e
      return if e.response.body.blank?

      model.ed_fi_logs.create(
        school_year: school_year,
        endpoint: endpoint,
        json: body,
        response: e.response.body
      )
      false
    end
end
