module Populator
  def self.school(name, options={})
    unless Support::User.exists?
      support_user = Support::User.create(
        first_name: 'Support',
        last_name: 'User',
        username: 'support',
        password: 'guest',
        password_confirmation: 'guest'
      )
      support_user.create_permission(users: :manage)
    end

    options = { associated: true, school_year_type: 2 }.merge(options)

    school = School.new
    school.name = name
    school.motto = 'A place to be'
    school.time_zone = 'America/Chicago'
    school.active = 1
    school.logout_redirect = 0
    school.first_grade_offered = 0
    school.last_grade_offered = 12
    school.us_department_of_education = 1
    school.save

    FileUtils.mkdir_p(school.dir_path)

    puts "Creating SE#{school.id} - #{school.name}"

    config = SchoolConfig.new
    config.school = school
    config.color = 'ff9900'
    config.school_year_type = options[:school_year_type]
    config.classroom = 1
    config.admissions = 1
    config.save

    if options[:associated]
      school_year(school)
      families(school)
      users(school)
      classrooms(school)
    end

    school
  end

  def self.school_year(school, older=false)
    year = school.school_years.build
    if school.school_years.count.positive?
      ordered_years = school.school_years.order(:academic_year)
      year.academic_year =
        if older
          ordered_years.first.academic_year - 1
        else
          ordered_years.last.academic_year + 1
        end
    else
      year.current = 1
      year.academic_year = (Time.now.in_time_zone + 6.months).year
    end
    stop = year.academic_year
    start = year.academic_year - 1
    year.name = "#{start}-#{stop}"

    print "Adding school year #{year.name} to SE#{school.id}..."

    case school.school_config.school_year_type.to_sym
    when :semesters # Semester / 4 Quarters
      s1_start = third_monday start, 8
      s1_end = third_monday start, 12
      s2_start = third_monday stop, 1
      s2_end = third_monday stop, 5

      dates = [*s1_start...s1_end, *s2_start...s2_end].select(&:on_weekday?)

      year.description = "#{year.name} School Year"
      year.q1_start = s1_start
      year.q2_start = third_monday start, 10
      year.q3_start = s2_start
      year.q4_start = third_monday stop, 3
      year.end = s2_end
      year.save

      quarters = [year.q4_start, year.q3_start]
      next_start = year.q2_start
    when :trimesters # Trimester
      q1_start = third_monday start, 8
      q1_end = third_monday start, 10
      q2_start = third_monday start, 11
      q2_end = third_monday stop, 2
      q3_start = third_monday stop, 3
      q3_end = third_monday stop, 5

      dates = [
        *q1_start...q1_end,
        *q2_start...q2_end,
        *q3_start...q3_end
      ].select(&:on_weekday?)

      year.description = "#{year.name} School Year"
      year.q1_start = q1_start
      year.q2_start = q2_start
      year.q3_start = q3_start
      year.end = q3_end
      year.save

      quarters = [year.q3_start]
      next_start = year.q2_start
    when :sessions # Session
      session_dates = {}

      session_dates[1] = third_monday start, 8
      session_dates[2] = third_monday start, 9
      session_dates[3] = third_monday start, 11
      session_dates[4] = third_monday start, 12
      session_dates[5] = third_monday stop, 1
      session_dates[6] = third_monday stop, 3

      first_day = session_dates[1]
      last_day = third_monday stop, 5

      dates = [*first_day...last_day].select(&:on_weekday?)

      year.description = "#{year.name} School Year"
      year.q1_start = session_dates[1]
      year.end = last_day
      year.save

      session = nil
      session_dates.each do |index, date|
        unless session.nil?
          session.end = date - 1
          session.save
        end

        session = school.school_year_sessions.build
        session.school_year = year
        session.sequence = index
        session.start = date
        session.name = "Session #{index}"
        session.description = "#{session.name} description"
      end
      session.end = last_day
      session.save

      quarters = session_dates.values.reverse
      quarters.pop # Remove 1st quarter we don't need it
      next_start = quarters.pop # Get quarter 2 for starter
    end

    quarter = 1
    dates.each do |date|
      day = school.school_days.build
      day.school_year = year
      day.date = date

      if quarters.length && date == next_start
        quarter += 1
        next_start = quarters.pop
      end

      day.quarter = quarter
      day.save
    end

    puts 'done'
  end

  def self.accounting_data(school)
    print 'Adding accounting data...'

    ['Music', 'Athletics', 'Speech', 'Drama', 'Cafeteria'].each do |name|
      category = school.accounting_categories.create(name: name)
      category.subcategories.create(
        name: 'General',
        viewable: true
      )
    end

    family = school.families.first
    amount = 5
    school.accounting_subcategories.each do |subcategory|
      family.accounting_increases.create(
        action: :charge,
        amount: amount,
        posted_on: Time.now.in_time_zone,
        memo: "#{subcategory.name} charge",
        student: school.students.first,
        subcategory: subcategory
      )
      amount += 5
    end

    school.create_payjunction_credential(username: 'sycamoredev', password: 'Sycamore123$')

    puts 'done'
  end

  def self.student_additional_fields(school)
    print 'Adding student additional fields...'

    additional_group_one = school.student_additional_groups.create(
      name: 'Student History'
    )

    additional_field_one = school.student_additional_fields.build(
      student_additional_group: additional_group_one
    )

    additional_field_one.name = 'Previous School'
    additional_field_one.description = 'Previous School Information'
    additional_field_one.type = :text
    additional_field_one.public = 1
    additional_field_one.admissions = 1
    additional_field_one.save

    additional_group_two = school.student_additional_groups.create(
      name: 'Extra Details'
    )

    additional_field_two = school.student_additional_fields.build(
      student_additional_group: additional_group_two
    )

    additional_field_two.name = 'English First Language'
    additional_field_two.description = 'English as first language'
    additional_field_two.type = :multi_choice
    additional_field_two.public = 1
    additional_field_two.admissions = 1
    additional_field_two.save

    additional_choice_one = additional_field_two
      .student_additional_choices
      .build

    additional_choice_one.school = school
    additional_choice_one.sequence = 1
    additional_choice_one.value = 'Yes'
    additional_choice_one.label = 'Yes'
    additional_choice_one.save

    additional_choice_two = additional_field_two
      .student_additional_choices
      .build

    additional_choice_two.school = school
    additional_choice_two.sequence = 2
    additional_choice_two.value = 'No'
    additional_choice_two.label = 'No'
    additional_choice_two.save

    additional_field_three = school.student_additional_fields.build
    additional_field_three.name = 'Enrollment Date'
    additional_field_three.description = 'Date expected to be enrolled'
    additional_field_three.type = :date
    additional_field_three.public = 1
    additional_field_three.admissions = 1
    additional_field_three.save

    puts 'done'
  end

  def self.family_additional_fields(school)
    print 'Adding family additional fields...'

    additional_group_one = school.family_additional_groups.create(name: 'Family History')

    additional_field_one = school.family_additional_fields.build(
      family_additional_group: additional_group_one
    )

    additional_field_one.save

    puts 'done'
  end

  def self.admission_data(school)
    print 'Adding admission data...'

    test_file_path = Rails.root.join('test.txt')
    File.open(test_file_path, 'w') { |file| file.write("Some text.\n") }
    test_file = Rack::Test::UploadedFile.new(test_file_path, 'text/plain')

    year = school.school_years.last
    school.create_admission_config(
      school_year: year,
      registration: true,
      portal: true
    )

    status_pending = school.admission_statuses.create(name: 'Pending')
    school.admission_statuses.create(name: 'Accepted')

    school.admission_statuses.create(
      name: 'Archived',
      archived: true
    )

    checkbox_one = school.admission_checkboxes.create(
      name: 'Immunizations',
      description: 'Submitted immunization history'
    )

    checkbox_two = school.admission_checkboxes.create(
      name: 'Library Fee',
      description: 'Paid library fee'
    )

    essay_one = school.admission_essays.create(
      name: 'Greatest strength',
      body: 'Describe your greatest strength.'
    )

    essay_two = school.admission_essays.create(
      name: 'Greatest weakness',
      body: 'Describe your greatest weakness.'
    )

    agreement_one = school.admission_agreements.create(
      name: 'Photo release',
      body: 'I authorize the use of photographs of my child in school publications.'
    )

    agreement_two = school.admission_agreements.create(
      name: 'Student handbook',
      body: 'I have read and agree to the terms of the student handbook.'
    )

    school.admission_agreements.create(
      name: 'Communist sympathies',
      body: 'My child is not now and has never been a member of the communist party.'
    )

    document_one = school.admission_documents.create(
      name: 'Birth Certificate',
      description: 'Certificate of Birth'
    )

    document_two = school.admission_documents.create(
      name: 'Drivers License',
      description: 'License of Driving'
    )

    attachment_one = school.admission_attachments.create(
      name: 'Student Handbook',
      description: 'Handbook for Students',
      file: test_file
    )

    attachment_two = school.admission_attachments.create(
      name: 'School Supplies',
      description: 'Supplies for School',
      file: test_file
    )

    grades = school.grades_hash.keys

    applications = []

    application = school.admission_applications.build
    application.school_year = year
    application.name = "#{year.name} All Grades"
    application.open = true
    applications.push application

    application = school.admission_applications.build
    application.enrollment = true
    application.school_year = year
    application.name = "#{year.name} Returning"
    application.returning_students = true
    application.open = true
    applications.push application

    applications.each do |app|
      grades.each do |grade|
        app.application_grades.build(grade: grade, available: true)
      end
      app.save
    end

    application = school.admission_applications.build
    application.enrollment = true
    application.school_year = year
    application.name = "#{year.name} New Elementary"
    application.new_students = true
    application.open = true
    applications.push application

    grades.each do |grade|
      application.application_grades.build(grade: grade, available: true) if grade < 7
    end
    application.save

    application = school.admission_applications.build
    application.enrollment = true
    application.school_year = year
    application.name = "#{year.name} New High School"
    application.new_students = true
    application.open = true
    applications.push application

    grades.each do |grade|
      application.application_grades.build(grade: grade, available: true) if grade >= 7
    end
    application.save

    applications.each do |app|
      app.checkboxes << checkbox_one
      app.checkboxes << checkbox_two

      app.profile_fields.create(field: :email, required: true)

      app.essays << essay_one
      app.essays << essay_two

      app.documents << document_one
      app.documents << document_two

      app.attachments << attachment_one
      app.attachments << attachment_two

      app.agreements << agreement_one
      app.agreements << agreement_two
    end

    application = applications.first

    family = school.families.first
    family.admission_family_revisions.create(school_year: year)
    family.admission_medical_revisions.create(school_year: year)
    family.admission_contact_revisions.create(
      school_year: year, contact_family: family.contact_families.first
    )

    applicant = family.admission_applicants.build
    applicant.application = application
    applicant.first_name = 'Nemo'
    applicant.last_name = 'Current'
    applicant.date_of_birth = '2000-10-31'
    applicant.grade = 10
    applicant.status = status_pending
    applicant.state = :pending
    applicant.email = 'nemo@example.com'
    applicant.save

    essay = applicant.applicant_essays.build
    essay.essay = application.essays.first
    essay.body = "I'm pretty awesome and you should just enroll me."
    essay.save

    applicant.applicant_documents.create(
      document: application.documents.first,
      file: test_file
    )

    agreement = applicant.applicant_agreements.build
    agreement.agreement = application.agreements.first
    agreement.response = true
    agreement.save

    school.student_additional_fields.each do |field|
      additional_field = application.additional_fields.build
      additional_field.student_additional_field = field
      additional_field.save

      additional_value = applicant.additional_values.build
      additional_value.student_additional_field = field
      additional_value.value =
        case field.type
        when 1
          'Tri-County'
        when 2
          field.student_additional_choices.first.value
        else
          Date.today.strftime('%m/%d/%Y')
        end

      additional_value.save
    end

    File.delete(test_file_path)

    puts 'done'
  end

  def self.classrooms(school)
    print 'Adding classrooms...'

    employee = school.users.find_by(last_name: 'Employee')

    class_names = ['English', 'History', 'Math', 'Science']

    class_names.each do |name|
      classroom = school.classrooms.build
      classroom.name = classroom.description = name
      classroom.type = :period_long

      case school.school_config.school_year_type.to_sym
      when :semesters
        classroom.s1 = 1
        classroom.q1 = 1
        classroom.q2 = 1
        classroom.s2 = 1
        classroom.q3 = 1
        classroom.q4 = 1
      when :trimesters
        classroom.q1 = 1
        classroom.q2 = 1
        classroom.q3 = 1
        classroom.s1 = 1
        classroom.s2 = 1
        classroom.s3 = 1
      when :sessions
        classroom.q1 = 1
        classroom.q2 = 1
        classroom.q3 = 1
        classroom.q4 = 1
        classroom.q5 = 1
        classroom.q6 = 1
      end

      classroom.save

      employee.classrooms << classroom
    end

    puts 'done'
  end

  def self.families(school)
    print 'Adding families...'

    year = school.school_years.current

    contact = school.contacts.build
    contact.first_name = 'John'
    contact.last_name = 'Current'
    contact.title = Title.find_by(name: 'Mr.')
    contact.email = 'dev@sycamoreleaf.com'
    contact.save

    contact2 = school.contacts.build
    contact2.first_name = 'Jane'
    contact2.last_name = contact.last_name
    contact2.title = Title.find_by(name: 'Mrs.')
    contact2.email = 'dev@sycamoreleaf.com'
    contact2.save

    family = school.families.build
    family.name = "#{contact.last_name}, #{contact.first_name} and #{contact2.first_name}"
    family.code = school.generate_family_code_and_save(family.name)
    family.current = 1
    family.address = '321 First St'
    family.address_ext = 'Apt #1'
    family.city = 'Someplace'
    family.state = 'NE'
    family.zip = '54321'
    family.save

    family.school_years << year

    family.contact_families.create(
      contact: contact,
      relationship: Relationship.find_by(name: 'Father'),
      primary: true,
      emergency: true,
      pickup: true,
      school: school
    )

    family.contact_families.create(
      contact: contact2,
      relationship: Relationship.find_by(name: 'Mother'),
      primary: true,
      emergency: true,
      pickup: true,
      school: school
    )

    student = family.primary_students.build
    student.first_name = 'Stan'
    student.last_name = contact.last_name
    student.code = student.family.generate_student_code
    student.current = 1
    student.gender = 'M'
    student.grade = 10
    student.date_of_birth = (student.grade + 5).years.ago
    student.save

    student.school_year_students.create(
      school_year: year,
      current: 1,
      grade: student.grade,
      entry_date: year.q1_start
    )

    family = school.families.build
    family.name = 'Oz, Frank'
    family.code = school.generate_family_code_and_save(family.name)
    family.save

    puts 'done'
  end

  def self.users(school, family=true)
    print 'Adding users...'

    user = school.users.build
    user.first_name = 'John'
    user.last_name = 'Superuser'
    user.username = 'superuser'
    user.encrypted_password = 'guest'
    user.active = 1
    user.level = 4
    user.superuser = 1
    user.family_id = 0
    user.student_id = 0
    user.terms_of_service_date = Time.current
    user.save(validate: false)

    user = school.users.build
    user.first_name = 'Tom'
    user.last_name = 'Employee'
    user.username = 'employee'
    user.encrypted_password = 'guest'
    user.active = 1
    user.level = 2
    user.family_id = 0
    user.student_id = 0
    user.terms_of_service_date = Time.current
    user.save(validate: false)

    if family
      user = school.users.build
      user.first_name = 'John'
      user.last_name = 'Current'
      user.username = 'current'
      user.encrypted_password = 'guest'
      user.active = 1
      user.level = 0
      user.family = school.families.first
      user.student_id = 0
      user.terms_of_service_date = Time.current
      user.save(validate: false)
    end

    user = school.users.build(
      first_name: 'Stan',
      last_name: 'Current',
      username: 'student',
      encrypted_password: 'guest',
      active: 1,
      family: school.families.first,
      student: school.students.first,
      terms_of_service_date: Time.current
    )
    user.save(validate: false)

    puts 'done'
  end

  def self.district(name)
    office = school("#{name} District Office", associated: false)
    office.update(school_district_office: 1)
    users(office, false)
    district = SchoolDistrict.create(name: "#{name} District", office: office)
    district.schools << school("#{name} School")
    district
  end

  def self.third_monday(year, month)
    date = Date.new year, month, 1
    offset = 1 - date.wday
    offset += 7 if offset.negative?
    date + offset + 14
  end
end
