require "csv"
require "activerecord-import"
require "zip"
require_relative "./report_processor"

module CanvasSync
  module Processors
    class ProvisioningReportProcessor < ReportProcessor
      # Processes a provisioning report using the bulk importer.
      #
      # options must contain a models key. If there is only one model
      # Canvas downloads the single report directly as a CSV. If it's
      # more than one model Canvas downloads a ZIP file, so we have to
      # extract that and iterate through it for processing.
      #
      # @param report_file_path [String]
      # @param options [Hash]
      def self.process(report_file_path, options)
        new(report_file_path, options)
      end

      def initialize(report_file_path, options) # rubocop:disable Metrics/AbcSize
        @options = options

        if options[:models].length == 1
          run_import(options[:models][0], report_file_path)
        else
          unzipped_file_path = extract(report_file_path)
          Dir[unzipped_file_path + "/*.csv"].each do |file_path|
            model_name = file_path.split("/").last.split(".").first
            run_import(model_name, file_path)
          end
        end
      end

      private

      def extract(file_path)
        unzipped_file_path = "#{file_path}_unzipped"

        Zip::File.open(file_path) do |zip_file|
          zip_file.each do |f|
            f_path = File.join(unzipped_file_path, f.name)
            FileUtils.mkdir_p(File.dirname(f_path))
            zip_file.extract(f, f_path) unless File.exist?(f_path)
          end
        end

        unzipped_file_path
      end

      def run_import(model_name, report_file_path)
        if @options[:legacy_support]
          CanvasSync::Importers::LegacyImporter.import(
            report_file_path,
            model_name.singularize.capitalize.constantize,
            @options[:account_id],
          )
        else
          send("bulk_process_#{model_name}", report_file_path)
        end
      end

      def bulk_process_users(report_file_path)
        CanvasSync::Importers::BulkImporter.import(
          report_file_path,
          mapping[:users][:report_columns],
          User,
          mapping[:users][:conflict_target].to_sym,
        )
      end

      def bulk_process_accounts(report_file_path)
        CanvasSync::Importers::BulkImporter.import(
          report_file_path,
          mapping[:accounts][:report_columns],
          Account,
          mapping[:accounts][:conflict_target].to_sym
        )
      end

      def bulk_process_courses(report_file_path)
        CanvasSync::Importers::BulkImporter.import(
          report_file_path,
          mapping[:courses][:report_columns],
          Course,
          mapping[:courses][:conflict_target].to_sym,
        )
      end

      def bulk_process_enrollments(report_file_path)
        CanvasSync::Importers::BulkImporter.import(
          report_file_path,
          mapping[:enrollments][:report_columns],
          Enrollment,
          mapping[:enrollments][:conflict_target].to_sym,
        )
      end

      def bulk_process_sections(report_file_path)
        CanvasSync::Importers::BulkImporter.import(
          report_file_path,
          mapping[:sections][:report_columns],
          Section,
          mapping[:sections][:conflict_target].to_sym,
        )
      end

      def bulk_process_xlist(report_file_path)
        CanvasSync::Importers::BulkImporter.import(
          report_file_path,
          mapping[:xlist][:report_columns],
          Section,
          mapping[:xlist][:conflict_target].to_sym,
        )
      end
    end
  end
end