# frozen_string_literal: true

require 'dry-types'
require 'bigdecimal'

module AcaEntities
  # Extend DryTypes
  # rubocop:disable Metrics/ModuleLength
  module Types
    send(:include, Dry.Types)
    send(:include, Dry::Logic)

    # Money = ::Types.Instance(BigDecimal)
    Money = Types.Constructor(BigDecimal) { |val| BigDecimal(val.to_s) }

    # @!attribute [r] HbxIdentifierKind
    # General data type for HBX-assigned identifiers
    # String, min length: 1 character, max length: 15 characters, numeric-only
    HbxIdentifierKind = Types::String.constrained(format: /^[0-9]{1,15}$/)

    McrToCvIncarcerationKind =
      Types.Constructor(self) { |value| value == 'INCARCERATED' }

    UsStateAbbreviationKind =
      Types::String.enum(
        'AL',
        'AK',
        'AS',
        'AZ',
        'AR',
        'CA',
        'CO',
        'CT',
        'DE',
        'DC',
        'FM',
        'FL',
        'GA',
        'GU',
        'HI',
        'ID',
        'IL',
        'IN',
        'IA',
        'KS',
        'KY',
        'LA',
        'ME',
        'MH',
        'MD',
        'MA',
        'MI',
        'MN',
        'MS',
        'MO',
        'MT',
        'NE',
        'NV',
        'NH',
        'NJ',
        'NM',
        'NY',
        'NC',
        'ND',
        'MP',
        'OH',
        'OK',
        'OR',
        'PW',
        'PA',
        'PR',
        'RI',
        'SC',
        'SD',
        'TN',
        'TX',
        'UT',
        'VT',
        'VI',
        'VA',
        'WA',
        'WV',
        'WI',
        'WY'
      )

    EmployeeStatusCodeKinds =
      Types::Coercible::String.enum(
        'NoLongerEmployed',
        'Retired',
        'CurrentlyEmployed'
      )

    LcsopCoverageCodeKinds =
      Types::Coercible::String.enum(
        'Offers',
        'DoesNotOffer',
        'PlansToOffer',
        'PlansToDrop',
        'PlansToChangeOptions',
        'Unknown',
        'PlansToChangeCost'
      )

    LcsopCostCodeKinds = LcsopCoverageCodeKinds

    EmployeeCoverageCode =
      Types::Coercible::String.enum(
        'Enrolled',
        'PlanningToEnroll',
        'NotEligible',
        'PlanningToDisenroll',
        'Eligible',
        'EligibleNotEnrolledPlanningToEnroll'
      )

    CoverageEndedReasonCode =
      Types::Coercible::String.enum(
        'UnpaidPremium',
        'DiscontinuedByIssuer',
        'DiscontinuedByEmployer',
        'ChangedEmployer'
      )

    OtherInsuranceTypeCode =
      Types::Coercible::String.enum(
        'Employer',
        'Private',
        'Medicaid',
        'Medicare',
        'CHIP',
        'TRICARE',
        'VeteranHealthProgram',
        'PeaceCorps',
        'OPM',
        'Federal',
        'State',
        'UnspecifiedLimitedCoverage',
        'UnspecifiedFullCoverage'
      )

    ClassOfAdmissionCodeMap = {
      # Immediate Relatives of U.S. Citizens
      IR1: 'Spouses, new arrivals',
      IR6: 'Spouses, adjustments',
      CR1: 'Spouses, new arrivals, conditional',
      CR6: 'Spouses, adjustments, conditional',
      IB1: 'Spouses, new arrivals, self petitioning',
      IB6: 'Spouses, adjustments, self petitioning',
      IW1: 'Spouses, widows or widowers, new arrivals',
      IW6: 'Spouses, widows or widowers, adjustments',
      CF1: 'Spouses, entered as fiance(e), adjustments, conditional',
      IF1: 'Spouses, entered as fiance(e), adjustments',
      IR2: 'Children, new arrivals',
      IR7: 'Children, adjustments',
      CR2: 'Children, new arrivals, conditional',
      CR7: 'Children, adjustments, conditional',
      AR1: 'Children, Amerasian, new arrivals',
      AR6: 'Children, Amerasian, adjustments',
      IB2: 'Children, new arrivals, self petitioning',
      IB7: 'Children, adjustments, self petitioning',
      IB3: 'Children of IB1 or IB6, new arrivals',
      IB8: 'Children of IB1 or IB6, adjustments',
      IW2: 'Children of IW1 or IW6, new arrivals',
      IW7: 'Children of IW1 or IW6, adjustments',
      CF2: 'Children of CF1, adjustments, conditional',
      IF2: 'Children of IF1, adjustments',
      IH3: 'Children adopted abroad under the Hague Convention, new arrivals',
      IH8: 'Children adopted abroad under the Hague Convention, adjustments',
      IH4: 'Children to be adopted under the Hague Convention, new arrivals',
      IH9: 'Children to be adopted under the Hague Convention, adjustments',
      IR3: 'Orphans adopted abroad, new arrivals',
      IR8: 'Orphans adopted abroad, adjustments',
      IR4: 'Orphans to be adopted, new arrivals',
      IR9: 'Orphans to be adopted, adjustments',
      IR5: 'Parents of adult U.S. citizens, new arrivals',
      IR0: 'Parents of adult U.S. citizens, adjustments',
      IB5:
        'Parents battered or abused, of U.S. citizens, new arrivals, self petitioning',
      IB0:
        'Parents battered or abused, of U.S. citizens, adjustments, self petitioning',
      # Family-sponsored preferences
      # Family members not included in the immediate relative class of
      # admission may be eligible for immigration under family-sponsored preferences.
      # Categories are organized by priority.

      # First: Unmarried sons/daughters of U.S. citizens and their children
      A11: 'Unmarried Amerasian sons/daughters of U.S. citizens, new arrivals',
      A16: 'Unmarried Amerasian sons/daughters of U.S. citizens, adjustments',
      F11: 'Unmarried sons/daughters of U.S. citizens, new arrivals',
      F16: 'Unmarried sons/daughters of U.S. citizens, adjustments',
      B11:
        'Unmarried sons/daughters of U.S. citizens, new arrivals, self petitioning',
      B16:
        'Unmarried sons/daughters of U.S. citizens, adjustments, self petitioning',
      A12: 'Children of A11 or A16, new arrivals',
      A17: 'Children of A11 or A16, adjustments',
      F12: 'Children of F11 or F16, new arrivals',
      F17: 'Children of F11 or F16, adjustments',
      B12: 'Children of B11 or B16, new arrivals',
      B17: 'Children of B11 or B16, adjustments',
      # Second: Spouses, children, and unmarried sons/daughters of alien residents
      F21:
        'Spouses of alien residents, subject to country limits, new arrivals',
      F26: 'Spouses of alien residents, subject to country limits, adjustments',
      B21:
        'Spouses of alien residents, subject to country limits, new arrivals, self petitioning',
      B26:
        'Spouses of alien residents, subject to country limits, adjustments, self petitioning',
      C21:
        'Spouses of alien residents, subject to country limits, new arrivals, conditional',
      C26:
        'Spouses of alien residents, subject to country limits, adjustments, conditional',
      FX1:
        'Spouses of alien residents, exempt from country limits, new arrivals',
      FX6:
        'Spouses of alien residents, exempt from country limits, adjustments',
      BX1:
        'Spouses of alien residents, exempt from country limits, new arrivals, self petitioning',
      BX6:
        'Spouses of alien residents, exempt from country limits, adjustments, self petitioning',
      CX1:
        'Spouses of alien residents, exempt from country limits, new arrivals, conditional',
      CX6:
        'Spouses of alien residents, exempt from country limits, adjustments, conditional',
      F22:
        'Children of alien residents, subject to country limits, new arrivals',
      F27:
        'Children of alien residents, subject to country limits, adjustments',
      B22:
        'Children of alien residents, subject to country limits, new arrivals, self petitioning',
      B27:
        'Children of alien residents, subject to country limits, adjustments, self petitioning',
      C23:
        'Children of C21, C22, C26, or C27, subject to country limits, new arrivals, conditional',
      C28:
        'Children of C21, C22, C26, or C27, subject to country limits, adjustments, conditional',
      B23:
        'Children of B21, B22, B26, or B27, subject to country limits, new arrivals',
      B28:
        'Children of B21, B22, B26, or B27, subject to country limits, adjustments',
      F23:
        'Children of F21, F22, F26, or F27, subject to country limits, new arrivals',
      F28:
        'Children of F21, F22, F26, or F27, subject to country limits, adjustments',
      C25:
        'Children of C24 or C29, subject to country limits, new arrivals, conditional',
      C20:
        'Children of C24 or C29, subject to country limits, adjustments, conditional',
      B25: 'Children of B24 or B29, subject to country limits, new arrivals',
      B20: 'Children of B24 or B29, subject to country limits, adjustments',
      F25: 'Children of F24 or F29, subject to country limits, new arrivals',
      F20: 'Children of F24 or F29, subject to country limits, adjustments',
      C22:
        'Children of alien residents, subject to country limits, new arrivals, conditional',
      C27:
        'Children of alien residents, subject to country limits, adjustments, conditional',
      FX2:
        'Children of alien residents, exempt from country limits, new arrivals',
      FX7:
        'Children of alien residents, exempt from country limits, adjustments',
      BX2:
        'Children of alien residents, exempt from country limits, new arrivals, self petitioning',
      BX7:
        'Children of alien residents, exempt from country limits, adjustments, self petitioning',
      CX3:
        'Children of CX2 or CX7, exempt from country limits, new arrivals, conditional',
      CX8:
        'Children of CX2 or CX7, exempt from country limits, adjustments, conditional',
      BX3:
        'Children of BX1, BX2, BX6, or BX7, exempt from country limits, new arrivals',
      BX8:
        'Children of BX1, BX2, BX6, or BX7, exempt from country limits, adjustments',
      FX3:
        'Children of FX1, FX2, FX7, or FX8, exempt from country limits, new arrivals',
      FX8:
        'Children of FX1, FX2, FX7, or FX8, exempt from country limits, adjustments',
      CX2:
        'Children of alien residents, exempt from country limits, new arrivals, conditional',
      CX7:
        'Children of alien residents, exempt from country limits, adjustments, conditional',
      F24:
        'Unmarried sons/daughters of alien residents, subject to country limits, new arrivals',
      F29:
        'Unmarried sons/daughters of alien residents, subject to country limits, adjustments',
      B24:
        'Unmarried sons/daughters of alien residents, subject to country limits, new arrivals, self petitioning',
      B29:
        'Unmarried sons/daughters of alien residents, subject to country limits, adjustments, self petitioning',
      C24:
        'Unmarried children of alien residents, subject to country limits, new arrivals, conditional',
      C29:
        'Unmarried children of alien residents, subject to country limits, adjustments, conditional',
      # Third: Married sons/daughters of U.S. citizens and their spouses and children
      A31: 'Married Amerasian sons/daughters of U.S. citizens, new arrivals',
      F31: 'Married sons/daughters of U.S. citizens, new arrivals',
      C31: 'Married sons/daughters of U.S. citizens, new arrivals, conditional',
      B31:
        'Married sons/daughters of U.S. citizens, new arrivals, self petitioning',
      A36: 'Married Amerasian sons/daughters of U.S. citizens, adjustments',
      F36: 'Married sons/daughters of U.S. citizens, adjustments',
      C36: 'Married sons/daughters of U.S. citizens, adjustments, conditional',
      B36:
        'Married sons/daughters of U.S. citizens, adjustments, self petitioning',
      A32: 'Spouses of A31 or A36, new arrivals',
      A37: 'Spouses of A31 or A36, adjustments',
      F32: 'Spouses of married sons/daughters of U.S. citizens, new arrivals',
      F37: 'Spouses of married sons/daughters of U.S. citizens, adjustments',
      C32: 'Spouses of C31 or C36, new arrivals, conditional',
      C37:
        'Spouses of married sons/daughters of U.S. citizens, adjustments, conditional',
      B32: 'Spouses of B31 or B36, new arrivals',
      B37: 'Spouses of B31 or B36, adjustments',
      A33: 'Children of A31 or A36, subject to country limits, new arrivals',
      A38: 'Children of A31 or A36, subject to country limits, adjustments',
      F33: 'Children of married sons/daughters of U.S. citizens, new arrivals',
      F38: 'Children of married sons/daughters of U.S. citizens, adjustments',
      C33:
        'Children of C31 or C36, subject to country limits, new arrivals, conditional',
      C38:
        'Children of C31 or C36, subject to country limits, adjustments, conditional',
      B33: 'Children of B31 or B36, subject to country limits, new arrivals',
      B38: 'Children of B31 or B36, subject to country limits, adjustments',
      # Fourth: Brothers/sisters of U.S. citizens (at least 21 years of age) and their spouses and children

      F41: 'Brothers/sisters of U.S. citizens, new arrivals',
      F46: 'Brothers/sisters of U.S. citizens, adjustments',
      F42: 'Spouses of brothers/sisters of U.S. citizens, new arrivals',
      F47: 'Spouses of brothers/sisters of U.S. citizens, adjustments',
      F43: 'Children of brothers/sisters of U.S. citizens, new arrivals',
      F48: 'Children of brothers/sisters of U.S. citizens, adjustments',
      # Employment-based preferences
      # Those seeking to provide needed skills in the U.S. workforce or invest in new U.S.
      # jobs may be eligible to immigrate under employment-based preferences.
      # Categories are organized by priority.

      # First: Priority workers
      E11: 'Aliens with extraordinary ability, new arrivals',
      E16: 'Aliens with extraordinary ability, adjustments',
      E12: 'Outstanding professors or researchers, new arrivals',
      E17: 'Outstanding professors or researchers, adjustments',
      E13: 'Multinational executives or managers, new arrivals',
      E18: 'Multinational executives or managers, adjustments',
      E14: 'Spouses of E11, E12, E13, E16, E17, or E18, new arrivals',
      E19: 'Spouses of E11, E12, E13, E16, E17, or E18, adjustments',
      E15: 'Children of E11, E12, E13, E16, E17, or E18, new arrivals',
      E10: 'Children of E11, E12, E13, E16, E17, or E18, adjustments',
      # Second: Professionals with advanced degrees or aliens of exceptional ability
      E21: 'Professionals holding advanced degrees, new arrivals',
      E26: 'Professionals holding advanced degrees, adjustments',
      ES1: 'Soviet scientists, new arrivals',
      ES6: 'Soviet scientists, adjustments',
      E22: 'Spouses of E21 or E26, new arrivals',
      E27: 'Spouses of E21 or E26, adjustments',
      E23: 'Children of E21 or E26, new arrivals',
      E28: 'Children of E21 or E26, adjustments',
      # Third: Skilled workers, professionals, and needed unskilled workers
      EX1: 'Schedule - A worker, new arrivals',
      EX6: 'Schedule - A worker, adjustments',
      E31: 'Skilled workers, new arrivals',
      E36: 'Skilled workers, adjustments',
      E32: 'Professionals with baccalaureate degrees, new arrivals',
      E37: 'Professionals with baccalaureate degrees, adjustments',
      EW3: 'Needed unskilled workers, new arrivals',
      EW8: 'Needed unskilled workers, adjustments',
      EC6: 'Chinese Student Protection Act (CSPA) principals, adjustments',
      EX2: 'Spouses of EX1 or EX6, new arrivals',
      EX7: 'Spouses of EX1 or EX6, adjustments',
      E34: 'Spouses of E31, E32, E36, or E37, new arrivals',
      E39: 'Spouses of E31, E32, E36, or E37, adjustments',
      EW4: 'Spouses of EW3 or EW8, new arrivals',
      EW9: 'Spouses of EW3 or EW8, adjustments',
      EC7: 'Spouses of EC6, adjustments',
      EX3: 'Children of EX1 or EX6, new arrivals',
      EX8: 'Children of EX1 or EX6, adjustments',
      E35: 'Children of E31, E32, E36, or E37, new arrivals',
      E30: 'Children of E31, E32, E36, or E37, adjustments',
      EW5: 'Children of EW3 or EW8, new arrivals',
      EW0: 'Children of EW3 or EW8, adjustments',
      EC8: 'Children of EC6, adjustments',
      # Fourth: Certain special immigrants
      BC1: 'Broadcast (IBCB of BBG) employees, new arrivals',
      BC6: 'Broadcast (IBCG of BBG) employees, adjustments',
      SD1: 'Ministers, new arrivals',
      SD6: 'Ministers, adjustments',
      SE1: 'Employees of U.S. government abroad, new arrivals',
      SE6: 'Employees of U.S. government abroad, adjustments',
      SF1:
        'Former employees of the Panama Canal Company or Canal Zone Government, new arrivals',
      SF6:
        'Former employees of the Panama Canal Company or Canal Zone Government, adjustments',
      SG1:
        'Former U.S. government employees in the Panama Canal Zone, new arrivals',
      SG6:
        'Former U.S. government employees in the Panama Canal Zone, adjustments',
      SH1:
        'Former employees of the Panama Canal Company or Canal Zone government, employed on April 1, 1979, new arrivals',
      SH6:
        'Former employees of the Panama Canal Company or Canal Zone government, employed on April 1, 1979, adjustments',
      SJ6:
        'Foreign medical school graduate who was licensed to practice in the United States on Jan. 9, 1978, adjustments',
      SK1: 'Retired employees of international organizations, new arrivals',
      SK6: 'Retired employees of international organizations, adjustments',
      SK4:
        'Certain surviving spouses of deceased international organization employees, new arrivals',
      SK9:
        'Certain surviving spouses of deceased international organization employees, adjustments',
      SL1: 'Juvenile court dependents, new arrivals',
      SL6: 'Juvenile court dependents, adjustments',
      SN1: 'Retired NATO-6 civilian employees, new arrivals',
      SN6: 'Retired NATO-6 civilian employees, adjustments',
      SR1: 'Religious workers, new arrivals',
      SR6: 'Religious workers, adjustments',
      SN4:
        'Certain surviving spouses of deceased NATO-6 civilian employees, new arrivals',
      SN9:
        'Certain surviving spouses of deceased NATO-6 civilian employees, adjustments',
      BC2: 'Spouses of BC1 or BC6, new arrivals',
      BC7: 'Spouses of BC1 or BC6, adjustments',
      SD2: 'Spouses of SD1 or SD6, new arrivals',
      SD7: 'Spouses of SD1 or SD6, adjustments',
      SE2: 'Spouses of SE1 or SE6, new arrivals',
      SE7: 'Spouses of SE1 or SE6, adjustments',
      SF2: 'Spouses or children of SF1 or SF6, new arrivals',
      SF7: 'Spouses or children of SF1 or SF6, adjustments',
      SG2: 'Spouses or children of SG1 or SG6, new arrivals',
      SG7: 'Spouses or children of SG1 or SG6, adjustments',
      SH2: 'Spouses or children of SH1 or SH6, new arrivals',
      SH7: 'Spouses or children of SH1 or SH6, adjustments',
      SJ2: 'Spouses or children of SJ6, new arrivals',
      SJ7: 'Spouses or children of SJ6, adjustments',
      SK2: 'Spouses of SK1 or SK6, new arrivals',
      SK7: 'Spouses of SK1 or SK6, adjustments',
      SN2: 'Spouses of SN1 of SN6, new arrivals',
      SN7: 'Spouses of SN1 of SN6, adjustments',
      SR2: 'Spouses of SR1 or SR6, new arrivals',
      SR7: 'Spouses of SR1 or SR6, adjustments',
      BC3: 'Children of BC1 or BC6, new arrivals',
      BC8: 'Children of BC1 or BC6, adjustments',
      SD3: 'Children of SD1 or SD6, new arrivals',
      SD8: 'Children of SD1 or SD6, adjustments',
      SE3: 'Children of SE1 or SE6, new arrivals',
      SE8: 'Children of SE1 or SE6, adjustments',
      SK3: 'Certain unmarried children of SK1 or SK6, new arrivals',
      SK8: 'Certain unmarried children of SK1 or SK6, adjustments',
      SR3: 'Children of SR1 or SR6, new arrivals',
      SR8: 'Children of SR1 or SR6, adjustments',
      SN3: 'Certain unmarried sons/daughters of SN1 or SN6, new arrivals',
      SN8: 'Certain unmarried sons/daughters of SN1 or SN6, adjustments',
      # Fifth: Employment creation (investors)',
      C51:
        'Employment creation, not in targeted area, new arrivals, conditional',
      C56:
        'Employment creation, not in targeted area, adjustments, conditional',
      E51: 'Employment creation, new arrivals',
      E56: 'Employment creation, adjustments',
      I51:
        'Employment creation, targeted area, pilot program, new arrivals, conditional',
      I56:
        'Employment creation, targeted area, pilot program, adjustments, conditional',
      T51: 'Employment creation, targeted area, new arrivals, conditional',
      T56: 'Employment creation, targeted area, adjustments, conditional',
      R51: 'Investor pilot program, not targeted, new arrivals, conditional',
      R56: 'Investor pilot program, not targeted, adjustments, conditional',
      C52: 'Spouses of C51 or C56, new arrivals, conditional',
      C57: 'Spouses of C51 or C56, adjustments, conditional',
      E52: 'Spouses of E51 or E56, new arrivals',
      E57: 'Spouses of E51 or E56, adjustments',
      I52: 'Spouses of I51 or I56, new arrivals, conditional',
      I57: 'Spouses of I51 or I56, adjustments, conditional',
      T52: 'Spouses of T51 or T56, new arrivals, conditional',
      T57: 'Spouses of T51 or T56, adjustments, conditional',
      R52: 'Spouses of R51 or R56, new arrivals, conditional',
      R57: 'Spouses of R51 or R56, adjustments, conditional',
      C53: 'Children of C51 or C56, new arrivals, conditional',
      C58: 'Children of C51 or C56, adjustments, conditional',
      E53: 'Children of E51 or E56, new arrivals',
      E58: 'Children of E51 or E56, adjustments',
      I53: 'Children of I51 or I56, new arrivals, conditional',
      I58: 'Children of I51 or I56, adjustments, conditional',
      T53: 'Children of T51 or T56, new arrivals, conditional',
      T58: 'Children of T51 or T56, adjustments, conditional',
      R53: 'Children of R51 or R56, new arrivals, conditional',
      R58: 'Children of R51 or R56, adjustments, conditional',
      # Refugees and Asylees
      # The United States provides refuge to persons who have been persecuted or
      # have a well-founded fear of persecution through two programs:
      # a refugee program for persons outside the United States and their immediate relatives,
      # and an asylum program for persons in the United States and their immediate relatives.

      # Refugees',
      CU6: 'Cuban refugees (P.L. 89-732 of 1966)',
      CU7: 'Non-Cuban spouses or children of Cuban refugees',
      IC6: 'Indochinese refugees (P.L. 95-145 of 1977)',
      IC7:
        'Spouses or children of Indochinese refugees not qualified as refugees on their own',
      R86: 'Refugee parolees (P.L. 95-412 of 1978)',
      M83:
        'Refugee escapees previously admitted for lawful permanent resident status, adjustments',
      Y64: 'Refugees in the United States prior to July 1, 1953, adjustments',
      RE6: 'Other refugees (P.L. 96-212 Refugee Act of 1980)',
      RE7: 'Spouses of RE6',
      RE8: 'Children of RE6',
      RE9: 'Other relatives',
      # Asylees',
      AS6: 'Asylees',
      GA6: 'Iraqi asylees',
      SY6: 'Syrian asylees',
      AS7: 'Spouses of AS6',
      GA7: 'Spouses of GA6',
      SY7: 'Spouses of SY6',
      AS8: 'Children of AS6',
      GA8: 'Children of GA6',
      SY8: 'Children of SY6',
      # Diversity
      # Those who seek to immigrate to the United States from countries with relatively
      # low levels of immigration may be eligible to seek immigration under the
      # Diversity Immigrant Visa Program.

      # Diversity',
      DV1: 'Principals, new arrivals',
      DV6: 'Principals, adjustments',
      DV2: 'Spouses of DV1 or DV6, new arrivals',
      DV7: 'Spouses of DV1 or DV6, adjustments',
      DV3: 'Children of DV1 or DV6, new arrivals',
      DV8: 'Children of DV1 or DV6, adjustments',
      # Other
      # Remaining admission categories are generally limited to persons admitted under special legislation.

      # Parolees',
      PH6: 'Parolees, Polish/Hungarian',
      LA6: 'Parolees, Soviet/Indochinese',
      ID6: 'Parolees, Indochinese',
      M93:
        'Parolees, Hungarian previously admitted for lawful permanent resident status',
      NA3: 'Children born abroad to alien residents',
      # Nicaraguan and Central American Relief Act (NACARA Section 202, P.L. 105-100)',
      NC6: 'Principals',
      NC7: 'Spouses of NC6',
      NC8: 'Children of NC6',
      NC9: 'Unmarried sons/daughters of NC6',
      # Cancellation of removal',
      Z13: 'Sec. 244, P.L. 89-236, subject to 4,000 annual limit',
      Z14:
        'Battered spouses or children (Violence Against Women Act), P.L. 103-322 of 1994, subject to 4,000 annual limit',
      Z15:
        'Salvadoran, Guatemalan and former Soviet bloc country nationals (NACARA Section 203, P.L. 105-100 of 1997)',
      Z56:
        'Crewmen who entered on or before June 30, 1964 and are immediate relatives of U.S. citizens or special immigrants',
      Z57:
        'Crewmen who entered on or before June 30, 1964 and are preference or non-preference immigrants',
      Z11: 'Preference or non-preference immigrants (other than crewmen)',
      # Haitian Refugee Immigration Fairness Act (HRIFA, P.L. 105-277)',
      HA6: 'Haitian asylum applicants',
      HB6: 'Haitian parolees',
      HC6: 'Haitian children without parents',
      HD6: 'Haitian children orphaned in the United States',
      HE6: 'Haitian children abandoned by parents',
      HA7: 'Spouses of HA6',
      HB7: 'Spouses of HB6',
      HC7: 'Spouses of HC6',
      HD7: 'Spouses of HD6',
      HE7: 'Spouses of HE6',
      HA8: 'Children of HA6',
      HB8: 'Children of HB6',
      HC8: 'Children of HC6',
      HD8: 'Children of HD6',
      HE8: 'Children of HE6',
      HA9: 'Unmarried sons/daughters of HA6',
      HB9: 'Unmarried sons/daughters of HB6',
      HC9: 'Unmarried sons/daughters of HC6',
      HD9: 'Unmarried sons/daughters of HD6',
      HE9: 'Unmarried sons/daughters of HE6',
      # IRCA legalization',
      W16: 'Entered without inspection before 1/1/82',
      W26: 'Entered as nonimmigrant and overstayed visa before 1/1/82',
      W36: 'Blanket enforced voluntary departure (EVD) group',
      S16:
        'Seasonal Agricultural Workers (SAW), worked at least 90 days during each year ending May 1, 1984, 1985, and 1986',
      S26:
        'Seasonal Agricultural Workers (SAW), worked at least 90 days during the year ending on May 1, 1986',
      # IRCA legalization dependents',
      LB1: 'Spouses of legalized aliens, new arrivals',
      CB1: 'Spouses of legalized aliens, new arrivals, conditional',
      LB6: 'Spouses of legalized aliens, adjustments',
      CB6: 'Spouses of legalized aliens, adjustments, conditional',
      LB2: 'Children of LB1 or LB6, new arrivals',
      CB2: 'Children of CB1 or CB6, new arrivals, conditional',
      LB7: 'Children of LB1 or LB6, adjustments',
      CB7: 'Children of CB1 or CB6, adjustments, conditional',
      # Other classes",
      AA1: 'Natives of certain adversely affected foreign states, new arrivals',
      AA6: 'Natives of certain adversely affected foreign states, adjustments',
      AA2: 'Spouses of AA1 or AA6, new arrivals',
      AA7: 'Spouses of AA1 or AA6, adjustments',
      AA3: 'Children of AA1 or AA6, new arrivals',
      AA8: 'Children of AA1 or AA6, adjustments',
      AM1: 'Amerasians, born in Vietnam between 1/1/62-1/1/76, new arrivals',
      AM6: 'Amerasians, born in Vietnam between 1/1/62-1/1/76, adjustments',
      AM2: 'Spouses or children of AM1 or AM6, new arrivals',
      AM7: 'Spouses or children of AM1 or AM6, adjustments',
      AM3: 'Mothers, guardians, or next of kin of AM1 or AM6, new arrivals',
      AM8: 'Mothers, guardians, or next of kin of AM1 or AM6, adjustments',
      DS1: 'Individuals born under diplomatic status, adjustments,',
      HH6: 'Parolees adjusting under the Help HAITI Act of 2010, adjustments',
      HK1: 'Hong Kong business employees, new arrivals',
      HK6: 'Hong Kong business employees, adjustments',
      HK2: 'Spouses of HK1 or HK6, new arrivals',
      HK7: 'Spouses of HK1 or HK6, adjustments',
      HK3: 'Children of HK1 or HK6, new arrivals',
      HK8: 'Children of HK1 or HK6, adjustments',
      CH6: 'Cuban Haitian entrants, adjustments (P.L. 99-603)',
      S13: 'American Indians born in Canada, new arrivals',
      DT1:
        'Natives of Tibet who continuously resided in Nepal or India (Displaced Tibetan), new arrivals',
      DT6:
        'Natives of Tibet who continuously resided in Nepal or India (Displaced Tibetan), adjustments',
      DT2: 'Spouses of DT1 or DT6, new arrivals',
      DT7: 'Spouses of DT1 or DT6, adjustments',
      DT3: 'Children of DT1 or DT6, new arrivals',
      DT8: 'Children of DT1 or DT6, adjustments',
      MR0:
        'Parents of U.S. citizens presumed to be lawful permanent resident aliens - Northern Mariana Islands, adjustments',
      MR6:
        'Spouses of U.S. citizens presumed to be lawful permanent resident aliens - Northern Mariana Islands, adjustments',
      MR7:
        'Children of U.S. citizens presumed to be lawful permanent resident aliens - Northern Mariana Islands, adjustments',
      NP8:
        'Alien who filed and was qualified with investor status prior to June 1, 1978',
      NP9: 'Spouses or children of NP8, adjustments',
      RN6: 'Certain former H1 nonimmigrant registered nurses, adjustments',
      RN7: 'Spouses or children of RN6, adjustments',
      SC1: 'Lost citizenship through marriage, new arrivals',
      SC6: 'Lost citizenship through marriage, adjustments',
      SC2:
        'Lost citizenship through serving in foreign armed forces, new arrivals',
      SC7:
        'Lost citizenship through serving in foreign armed forces, adjustments',
      SI1:
        'Special immigrant interpreters who are nationals of Iraq or Afghanistan, new arrivals',
      SI6:
        'Special immigrant interpreters who are nationals of Iraq or Afghanistan, adjustments',
      SI2: 'Spouses of SI1 or SI6, new arrivals',
      SI7: 'Spouses of SI1 or SI6, adjustments',
      SI3: 'Children of SI1 or SI6, new arrivals',
      SI8: 'Children of SI1 or SI6, adjustments',
      SM1:
        'U.S. Armed Forces personnel, service (12 years) after 10/1/91, new arrivals',
      SM6:
        'U.S. Armed Forces personnel, service (12 years) after 10/1/91, adjustments',
      SM4:
        'U.S. Armed Forces personnel, service (12 years) by 10/91, new arrivals',
      SM9:
        'U.S. Armed Forces personnel, service (12 years) by 10/91, adjustments',
      SM2: 'Spouses of SM1 or SM6, new arrivals',
      SM7: 'Spouses of SM1 or SM6, adjustments',
      SM5: 'Spouses or children of SM4 or SM9, new arrivals',
      SM0: 'Spouses or children of SM4 or SM9, adjustments',
      SM3: 'Children of SM1 or SM6, new arrivals',
      SM8: 'Children of SM1 or SM6, adjustments',
      SQ1:
        'Certain Iraqis and Afghans employed by U.S. Government, new arrivals',
      SQ6:
        'Certain Iraqis and Afghans employed by U.S. Government, adjustments',
      SQ2: 'Spouses of SQ1 or SQ6, new arrivals',
      SQ7: 'Spouses of SQ1 or SQ6, adjustments',
      SQ3: 'Children of SQ1 or SQ6, new arrivals',
      SQ8: 'Children of SQ1 or SQ6, adjustments',
      ST6: 'Adjustment of T1 nonimmigrant',
      ST7: 'Adjustment of T2 nonimmigrant',
      ST8: 'Adjustment of T3 nonimmigrant',
      ST0: 'Adjustment of T4 nonimmigrant',
      ST9: 'Adjustment of T5 nonimmigrant',
      SU2: 'Spouses of SU6, new arrivals',
      SU3: 'Children of SU6, new arrivals',
      SU5: 'Parents of SU6, new arrivals',
      SU6: 'Adjustment of U1 nonimmigrant',
      SU7: 'Adjustment of U2 nonimmigrant',
      SU8: 'Adjustment of U3 nonimmigrant',
      SU0: 'Adjustment of U4 nonimmigrant',
      SU9: 'Adjustment of U5 nonimmigrant',
      W46: 'Late amnesty applicants (Immigration Reform and Control Act)',
      XB3: 'Presumed lawfully admitted for permanent residence',
      XA3:
        "Children born subsequent to issuance of parent's non-quota visa, new arrivals",
      XE3:
        "Children born subsequent to issuance of parent's employment-based preference visa, new arrivals",
      XF3:
        "Children born subsequent to issuance of parent's family-sponsored preference visa, new arrivals",
      XR3:
        "Children born subsequent to issuance of parent's immediate relative of U.S. citizen visa, new arrivals",
      XN3:
        "Children born subsequent to issuance of parent's visa other, new arrivals",
      Z43: 'Private bill, adjustments',
      Z33: 'Entered before 7/1/24, Section 249, P.L. 89-236, adjustments',
      Z03: 'Entered 7/1/24-6/28/40, Section 249, P.L. 89-236, adjustments',
      Z66: 'Entered 6/29/40-1/1/72, Section 249, P.L. 89-236, adjustments',
      Z83:
        'Foreign government official who is immediate relative of U.S. citizen or special immigrant'
    }.freeze

    ClassOfAdmissionCode =
      Types::Coercible::String.enum(
        'IR1',
        'IR6',
        'CR1',
        'CR6',
        'IB1',
        'IB6',
        'IW1',
        'IW6',
        'CF1',
        'IF1',
        'IR2',
        'IR7',
        'CR2',
        'CR7',
        'AR1',
        'AR6',
        'IB2',
        'IB7',
        'IB3',
        'IB8',
        'IW2',
        'IW7',
        'CF2',
        'IF2',
        'IH3',
        'IH8',
        'IH4',
        'IH9',
        'IR3',
        'IR8',
        'IR4',
        'IR9',
        'IR5',
        'IR0',
        'IB5',
        'IB0',
        'A11',
        'A16',
        'F11',
        'F16',
        'B11',
        'B16',
        'A12',
        'A17',
        'F12',
        'F17',
        'B12',
        'B17',
        'F21',
        'F26',
        'B21',
        'B26',
        'C21',
        'C26',
        'FX1',
        'FX6',
        'BX1',
        'BX6',
        'CX1',
        'CX6',
        'F22',
        'F27',
        'B22',
        'B27',
        'C23',
        'C28',
        'B23',
        'B28',
        'F23',
        'F28',
        'C25',
        'C20',
        'B25',
        'B20',
        'F25',
        'F20',
        'C22',
        'C27',
        'FX2',
        'FX7',
        'BX2',
        'BX7',
        'CX3',
        'CX8',
        'BX3',
        'BX8',
        'FX3',
        'FX8',
        'CX2',
        'CX7',
        'F24',
        'F29',
        'B24',
        'B29',
        'C24',
        'C29',
        'A31',
        'F31',
        'C31',
        'B31',
        'A36',
        'F36',
        'C36',
        'B36',
        'A32',
        'A37',
        'F32',
        'F37',
        'C32',
        'C37',
        'B32',
        'B37',
        'A33',
        'A38',
        'F33',
        'F38',
        'C33',
        'C38',
        'B33',
        'B38',
        'F41',
        'F46',
        'F42',
        'F47',
        'F43',
        'F48',
        'E11',
        'E16',
        'E12',
        'E17',
        'E13',
        'E18',
        'E14',
        'E19',
        'E15',
        'E10',
        'E21',
        'E26',
        'ES1',
        'ES6',
        'E22',
        'E27',
        'E23',
        'E28',
        'EX1',
        'EX6',
        'E31',
        'E36',
        'E32',
        'E37',
        'EW3',
        'EW8',
        'EC6',
        'EX2',
        'EX7',
        'E34',
        'E39',
        'EW4',
        'EW9',
        'EC7',
        'EX3',
        'EX8',
        'E35',
        'E30',
        'EW5',
        'EW0',
        'EC8',
        'BC1',
        'BC6',
        'SD1',
        'SD6',
        'SE1',
        'SE6',
        'SF1',
        'SF6',
        'SG1',
        'SG6',
        'SH1',
        'SH6',
        'SJ6',
        'SK1',
        'SK6',
        'SK4',
        'SK9',
        'SL1',
        'SL6',
        'SN1',
        'SN6',
        'SR1',
        'SR6',
        'SN4',
        'SN9',
        'BC2',
        'BC7',
        'SD2',
        'SD7',
        'SE2',
        'SE7',
        'SF2',
        'SF7',
        'SG2',
        'SG7',
        'SH2',
        'SH7',
        'SJ2',
        'SJ7',
        'SK2',
        'SK7',
        'SN2',
        'SN7',
        'SR2',
        'SR7',
        'BC3',
        'BC8',
        'SD3',
        'SD8',
        'SE3',
        'SE8',
        'SK3',
        'SK8',
        'SR3',
        'SR8',
        'SN3',
        'SN8',
        'C51',
        'C56',
        'E51',
        'E56',
        'I51',
        'I56',
        'T51',
        'T56',
        'R51',
        'R56',
        'C52',
        'C57',
        'E52',
        'E57',
        'I52',
        'I57',
        'T52',
        'T57',
        'R52',
        'R57',
        'C53',
        'C58',
        'E53',
        'E58',
        'I53',
        'I58',
        'T53',
        'T58',
        'R53',
        'R58',
        'CU6',
        'CU7',
        'IC6',
        'IC7',
        'R86',
        'M83',
        'Y64',
        'RE6',
        'RE7',
        'RE8',
        'RE9',
        'AS6',
        'GA6',
        'SY6',
        'AS7',
        'GA7',
        'SY7',
        'AS8',
        'GA8',
        'SY8',
        'DV1',
        'DV6',
        'DV2',
        'DV7',
        'DV3',
        'DV8',
        'PH6',
        'LA6',
        'ID6',
        'M93',
        'NA3',
        'NC6',
        'NC7',
        'NC8',
        'NC9',
        'Z13',
        'Z14',
        'Z15',
        'Z56',
        'Z57',
        'Z11',
        'HA6',
        'HB6',
        'HC6',
        'HD6',
        'HE6',
        'HA7',
        'HB7',
        'HC7',
        'HD7',
        'HE7',
        'HA8',
        'HB8',
        'HC8',
        'HD8',
        'HE8',
        'HA9',
        'HB9',
        'HC9',
        'HD9',
        'HE9',
        'W16',
        'W26',
        'W36',
        'S16',
        'S26',
        'LB1',
        'CB1',
        'LB6',
        'CB6',
        'LB2',
        'CB2',
        'LB7',
        'CB7',
        'AA1',
        'AA6',
        'AA2',
        'AA7',
        'AA3',
        'AA8',
        'AM1',
        'AM6',
        'AM2',
        'AM7',
        'AM3',
        'AM8',
        'DS1',
        'HH6',
        'HK1',
        'HK6',
        'HK2',
        'HK7',
        'HK3',
        'HK8',
        'CH6',
        'S13',
        'DT1',
        'DT6',
        'DT2',
        'DT7',
        'DT3',
        'DT8',
        'MR0',
        'MR6',
        'MR7',
        'NP8',
        'NP9',
        'RN6',
        'RN7',
        'SC1',
        'SC6',
        'SC2',
        'SC7',
        'SI1',
        'SI6',
        'SI2',
        'SI7',
        'SI3',
        'SI8',
        'SM1',
        'SM6',
        'SM4',
        'SM9',
        'SM2',
        'SM7',
        'SM5',
        'SM0',
        'SM3',
        'SM8',
        'SQ1',
        'SQ6',
        'SQ2',
        'SQ7',
        'SQ3',
        'SQ8',
        'ST6',
        'ST7',
        'ST8',
        'ST0',
        'ST9',
        'SU2',
        'SU3',
        'SU5',
        'SU6',
        'SU7',
        'SU8',
        'SU0',
        'SU9',
        'W46',
        'XB3',
        'XA3',
        'XE3',
        'XF3',
        'XR3',
        'XN3',
        'Z43',
        'Z33',
        'Z03',
        'Z66',
        'Z83'
      )

    IsoAlpha3Code =
      Types::Coercible::String.enum(
        'ABW',
        'AFG',
        'AGO',
        'AIA',
        'ALA',
        'ALB',
        'AND',
        'ARE',
        'ARG',
        'ARM',
        'ASM',
        'ATA',
        'ATF',
        'ATG',
        'AUS',
        'AUT',
        'AZE',
        'BDI',
        'BEL',
        'BEN',
        'BES',
        'BFA',
        'BGD',
        'BGR',
        'BHR',
        'BHS',
        'BIH',
        'BLM',
        'BLR',
        'BLZ',
        'BMU',
        'BOL',
        'BRA',
        'BRB',
        'BRN',
        'BTN',
        'BVT',
        'BWA',
        'CAF',
        'CAN',
        'CCK',
        'CHE',
        'CHL',
        'CHN',
        'CIV',
        'CMR',
        'COD',
        'COG',
        'COK',
        'COL',
        'COM',
        'CPV',
        'CRI',
        'CUB',
        'CUW',
        'CXR',
        'CYM',
        'CYP',
        'CZE',
        'DEU',
        'DJI',
        'DMA',
        'DNK',
        'DOM',
        'DZA',
        'ECU',
        'EGY',
        'ERI',
        'ESH',
        'ESP',
        'EST',
        'ETH',
        'FIN',
        'FJI',
        'FLK',
        'FRA',
        'FRO',
        'FSM',
        'GAB',
        'GBR',
        'GEO',
        'GGY',
        'GHA',
        'GIB',
        'GIN',
        'GLP',
        'GMB',
        'GNB',
        'GNQ',
        'GRC',
        'GRD',
        'GRL',
        'GTM',
        'GUF',
        'GUM',
        'GUY',
        'HKG',
        'HMD',
        'HND',
        'HRV',
        'HTI',
        'HUN',
        'IDN',
        'IMN',
        'IND',
        'IOT',
        'IRL',
        'IRN',
        'IRQ',
        'ISL',
        'ISR',
        'ITA',
        'JAM',
        'JEY',
        'JOR',
        'JPN',
        'KAZ',
        'KEN',
        'KGZ',
        'KHM',
        'KIR',
        'KNA',
        'KOR',
        'KWT',
        'LAO',
        'LBN',
        'LBR',
        'LBY',
        'LCA',
        'LIE',
        'LKA',
        'LSO',
        'LTU',
        'LUX',
        'LVA',
        'MAC',
        'MAF',
        'MAR',
        'MCO',
        'MDA',
        'MDG',
        'MDV',
        'MEX',
        'MHL',
        'MKD',
        'MLI',
        'MLT',
        'MMR',
        'MNE',
        'MNG',
        'MNP',
        'MOZ',
        'MRT',
        'MSR',
        'MTQ',
        'MUS',
        'MWI',
        'MYS',
        'MYT',
        'NAM',
        'NCL',
        'NER',
        'NFK',
        'NGA',
        'NIC',
        'NIU',
        'NLD',
        'NOR',
        'NPL',
        'NRU',
        'NZL',
        'OMN',
        'PAK',
        'PAN',
        'PCN',
        'PER',
        'PHL',
        'PLW',
        'PNG',
        'POL',
        'PRI',
        'PRK',
        'PRT',
        'PRY',
        'PSE',
        'PYF',
        'QAT',
        'REU',
        'ROU',
        'RUS',
        'RWA',
        'SAU',
        'SDN',
        'SEN',
        'SGP',
        'SGS',
        'SHN',
        'SJM',
        'SLB',
        'SLE',
        'SLV',
        'SMR',
        'SOM',
        'SPM',
        'SRB',
        'SSD',
        'STP',
        'SUR',
        'SVK',
        'SVN',
        'SWE',
        'SWZ',
        'SXM',
        'SYC',
        'SYR',
        'TCA',
        'TCD',
        'TGO',
        'THA',
        'TJK',
        'TKL',
        'TKM',
        'TLS',
        'TON',
        'TTO',
        'TUN',
        'TUR',
        'TUV',
        'TWN',
        'TZA',
        'UGA',
        'UKR',
        'UMI',
        'URY',
        'USA',
        'UZB',
        'VAT',
        'VCT',
        'VEN',
        'VGB',
        'VIR',
        'VNM',
        'VUT',
        'WLF',
        'WSM',
        'YEM',
        'ZAF',
        'ZMB',
        'ZWE'
      )

    IsoAlpha3CodeMapping = {
      ABW: 'Aruba',
      AFG: 'Afghanistan',
      AGO: 'Angola',
      AIA: 'Anguilla',
      ALA: 'Åland Islands',
      ALB: 'Albania',
      AND: 'Andorra',
      ARE: 'United Arab Emirates',
      ARG: 'Argentina',
      ARM: 'Armenia',
      ASM: 'American Samoa',
      ATA: 'Antarctica',
      ATF: 'French Southern Territories',
      ATG: 'Antigua and Barbuda',
      AUS: 'Australia',
      AUT: 'Austria',
      AZE: 'Azerbaijan',
      BDI: 'Burundi',
      BEL: 'Belgium',
      BEN: 'Benin',
      BES: 'Bonaire, Sint Eustatius and Saba',
      BFA: 'Burkina Faso',
      BGD: 'Bangladesh',
      BGR: 'Bulgaria',
      BHR: 'Bahrain',
      BHS: 'Bahamas',
      BIH: 'Bosnia and Herzegovina',
      BLM: 'Saint Barthélemy',
      BLR: 'Belarus',
      BLZ: 'Belize',
      BMU: 'Bermuda',
      BOL: 'Bolivia (Plurinational State of)',
      BRA: 'Brazil',
      BRB: 'Barbados',
      BRN: 'Brunei Darussalam',
      BTN: 'Bhutan',
      BVT: 'Bouvet Island',
      BWA: 'Botswana',
      CAF: 'Central African Republic',
      CAN: 'Canada',
      CCK: 'Cocos (Keeling) Islands',
      CHE: 'Switzerland',
      CHL: 'Chile',
      CHN: 'China',
      CIV: "Côte d'Ivoire",
      CMR: 'Cameroon',
      COD: 'Congo, Democratic Republic of the',
      COG: 'Congo',
      COK: 'Cook Islands',
      COL: 'Colombia',
      COM: 'Comoros',
      CPV: 'Cabo Verde',
      CRI: 'Costa Rica',
      CUB: 'Cuba',
      CUW: 'Curaçao',
      CXR: 'Christmas Island',
      CYM: 'Cayman Islands',
      CYP: 'Cyprus',
      CZE: 'Czechia',
      DEU: 'Germany',
      DJI: 'Djibouti',
      DMA: 'Dominica',
      DNK: 'Denmark',
      DOM: 'Dominican Republic',
      DZA: 'Algeria',
      ECU: 'Ecuador',
      EGY: 'Egypt',
      ERI: 'Eritrea',
      ESH: 'Western Sahara',
      ESP: 'Spain',
      EST: 'Estonia',
      ETH: 'Ethiopia',
      FIN: 'Finland',
      FJI: 'Fiji',
      FLK: 'Falkland Islands (Malvinas)',
      FRA: 'France',
      FRO: 'Faroe Islands',
      FSM: 'Micronesia (Federated States of)',
      GAB: 'Gabon',
      GBR: 'United Kingdom of Great Britain and Northern Ireland',
      GEO: 'Georgia',
      GGY: 'Guernsey',
      GHA: 'Ghana',
      GIB: 'Gibraltar',
      GIN: 'Guinea',
      GLP: 'Guadeloupe',
      GMB: 'Gambia',
      GNB: 'Guinea-Bissau',
      GNQ: 'Equatorial Guinea',
      GRC: 'Greece',
      GRD: 'Grenada',
      GRL: 'Greenland',
      GTM: 'Guatemala',
      GUF: 'French Guiana',
      GUM: 'Guam',
      GUY: 'Guyana',
      HKG: 'Hong Kong',
      HMD: 'Heard Island and McDonald Islands',
      HND: 'Honduras',
      HRV: 'Croatia',
      HTI: 'Haiti',
      HUN: 'Hungary',
      IDN: 'Indonesia',
      IMN: 'Isle of Man',
      IND: 'India',
      IOT: 'British Indian Ocean Territory',
      IRL: 'Ireland',
      IRN: 'Iran (Islamic Republic of)',
      IRQ: 'Iraq',
      ISL: 'Iceland',
      ISR: 'Israel',
      ITA: 'Italy',
      JAM: 'Jamaica',
      JEY: 'Jersey',
      JOR: 'Jordan',
      JPN: 'Japan',
      KAZ: 'Kazakhstan',
      KEN: 'Kenya',
      KGZ: 'Kyrgyzstan',
      KHM: 'Cambodia',
      KIR: 'Kiribati',
      KNA: 'Saint Kitts and Nevis',
      KOR: 'Korea, Republic of',
      KWT: 'Kuwait',
      LAO: "Lao People's Democratic Republic",
      LBN: 'Lebanon',
      LBR: 'Liberia',
      LBY: 'Libya',
      LCA: 'Saint Lucia',
      LIE: 'Liechtenstein',
      LKA: 'Sri Lanka',
      LSO: 'Lesotho',
      LTU: 'Lithuania',
      LUX: 'Luxembourg',
      LVA: 'Latvia',
      MAC: 'Macao',
      MAF: 'Saint Martin (French part)',
      MAR: 'Morocco',
      MCO: 'Monaco',
      MDA: 'Moldova, Republic of',
      MDG: 'Madagascar',
      MDV: 'Maldives',
      MEX: 'Mexico',
      MHL: 'Marshall Islands',
      MKD: 'North Macedonia',
      MLI: 'Mali',
      MLT: 'Malta',
      MMR: 'Myanmar',
      MNE: 'Montenegro',
      MNG: 'Mongolia',
      MNP: 'Northern Mariana Islands',
      MOZ: 'Mozambique',
      MRT: 'Mauritania',
      MSR: 'Montserrat',
      MTQ: 'Martinique',
      MUS: 'Mauritius',
      MWI: 'Malawi',
      MYS: 'Malaysia',
      MYT: 'Mayotte',
      NAM: 'Namibia',
      NCL: 'New Caledonia',
      NER: 'Niger',
      NFK: 'Norfolk Island',
      NGA: 'Nigeria',
      NIC: 'Nicaragua',
      NIU: 'Niue',
      NLD: 'Netherlands',
      NOR: 'Norway',
      NPL: 'Nepal',
      NRU: 'Nauru',
      NZL: 'New Zealand',
      OMN: 'Oman',
      PAK: 'Pakistan',
      PAN: 'Panama',
      PCN: 'Pitcairn',
      PER: 'Peru',
      PHL: 'Philippines',
      PLW: 'Palau',
      PNG: 'Papua New Guinea',
      POL: 'Poland',
      PRI: 'Puerto Rico',
      PRK: "Korea (Democratic People's Republic of)",
      PRT: 'Portugal',
      PRY: 'Paraguay',
      PSE: 'Palestine, State of',
      PYF: 'French Polynesia',
      QAT: 'Qatar',
      REU: 'Réunion',
      ROU: 'Romania',
      RUS: 'Russian Federation',
      RWA: 'Rwanda',
      SAU: 'Saudi Arabia',
      SDN: 'Sudan',
      SEN: 'Senegal',
      SGP: 'Singapore',
      SGS: 'South Georgia and the South Sandwich Islands',
      SHN: 'Saint Helena, Ascension and Tristan da Cunha',
      SJM: 'Svalbard and Jan Mayen',
      SLB: 'Solomon Islands',
      SLE: 'Sierra Leone',
      SLV: 'El Salvador',
      SMR: 'San Marino',
      SOM: 'Somalia',
      SPM: 'Saint Pierre and Miquelon',
      SRB: 'Serbia',
      SSD: 'South Sudan',
      STP: 'Sao Tome and Principe',
      SUR: 'Suriname',
      SVK: 'Slovakia',
      SVN: 'Slovenia',
      SWE: 'Sweden',
      SWZ: 'Eswatini',
      SXM: 'Sint Maarten (Dutch part)',
      SYC: 'Seychelles',
      SYR: 'Syrian Arab Republic',
      TCA: 'Turks and Caicos Islands',
      TCD: 'Chad',
      TGO: 'Togo',
      THA: 'Thailand',
      TJK: 'Tajikistan',
      TKL: 'Tokelau',
      TKM: 'Turkmenistan',
      TLS: 'Timor-Leste',
      TON: 'Tonga',
      TTO: 'Trinidad and Tobago',
      TUN: 'Tunisia',
      TUR: 'Turkey',
      TUV: 'Tuvalu',
      TWN: 'Taiwan, Province of China',
      TZA: 'Tanzania, United Republic of',
      UGA: 'Uganda',
      UKR: 'Ukraine',
      UMI: 'United States Minor Outlying Islands',
      URY: 'Uruguay',
      USA: 'United States of America',
      UZB: 'Uzbekistan',
      VAT: 'Holy See',
      VCT: 'Saint Vincent and the Grenadines',
      VEN: 'Venezuela (Bolivarian Republic of)',
      VGB: 'Virgin Islands (British)',
      VIR: 'Virgin Islands (U.S.)',
      VNM: 'Viet Nam',
      VUT: 'Vanuatu',
      WLF: 'Wallis and Futuna',
      WSM: 'Samoa',
      YEM: 'Yemen',
      ZAF: 'South Africa',
      ZMB: 'Zambia',
      ZWE: 'Zimbabwe'
    }.freeze

    ImmigrationDocumentTypeCode =
      Types::Coercible::String.enum(
        'AmericanSamoan',
        'CertificateOfCitizenship',
        'CubanHaitianEntrant',
        'Document',
        'DS2019',
        'I20',
        'I327',
        'I551',
        'I571',
        'I766',
        'I797',
        'I94',
        'I94InPassport',
        'MachineReadableVisa',
        'Native',
        'NaturalizationCertificate',
        'ORRCertification',
        'ORREligibilityLetter',
        'StayOfRemoval',
        'WithholdingOfRemoval',
        'TemporaryI551Stamp',
        'UnexpiredForeignPassport'
      )

    IndianTribeStateCode =
      Types::Coercible::String.enum(
        'Alabama',
        'Alaska',
        'Arizona',
        'California',
        'Colorado',
        'Connecticut',
        'Florida',
        'Idaho',
        'Indiana',
        'Iowa',
        'Kansas',
        'Louisiana',
        'Maine',
        'Massachusetts',
        'Michigan',
        'Minnesota',
        'Mississippi',
        'Montana',
        'Nebraska',
        'Nevada',
        'New Mexico',
        'New York',
        'North Carolina',
        'North Dakota',
        'Oklahoma',
        'Oregon',
        'Rhode Island',
        'South Carolina',
        'South Dakota',
        'Texas',
        'Utah',
        'Virginia',
        'Washington',
        'Wisconsin',
        'Wyoming'
      )

    CoverageTypeCode =
      Types::Coercible::String.enum(
        'CHIP',
        'EmergencyMedicaid',
        'RefugeeMedicalAssistance',
        'QHP',
        'Medicaid',
        'Dental'
      )

    MetalLevelCode =
      Types::Coercible::String.enum(
        'Platinum',
        'Gold',
        'Silver',
        'Bronze',
        'Catastrophic'
      )

    RelationshipToTaxFilerCodeMap = {
      '01': 'Spouse',
      '03': 'Parent (father or mother)',
      '04': 'Grandparent (grandfather or grandmother)',
      '05': 'Grandchild (grandson or granddaughter)',
      '06': 'Uncle or aunt',
      '07': 'Nephew or niece',
      '08': 'First cousin',
      '09': 'Adopted son or daughter',
      '10': 'Foster child (foster son or foster daughter)',
      '11': 'Son-in-law or daughter-in-law',
      '12': 'Brother-in-law or sister-in-law',
      '13': 'Mother-in-law or father-in law',
      '14': 'Sibling (brother or sister)',
      '15': 'Ward',
      '16': 'Stepparent (stepfather or stepmother)',
      '17': 'Stepchild (stepson or stepdaughter)',
      '18': 'Self',
      '19': 'Child (son or daughter)',
      '23': 'Sponsored dependent',
      '24': 'Dependent of a minor dependent',
      '25': 'Former spouse',
      '26': 'Guardian',
      '31': 'Court-appointed guardian',
      '38': 'Collateral dependent',
      '53': 'Domestic partner',
      '60': 'Annuitant',
      D2: 'Trustee',
      G8: 'Unspecified relationship',
      G9: 'Unspecified relative',
      '03-53': "Parent's domestic partner",
      '53-19': 'Child of domestic partner'
    }.freeze

    RelationshipToTaxFilerCode =
      Types::Coercible::String.enum(
        '01',
        '03',
        '04',
        '05',
        '06',
        '07',
        '08',
        '09',
        '10',
        '11',
        '12',
        '13',
        '14',
        '15',
        '16',
        '17',
        '18',
        '19',
        '23',
        '24',
        '25',
        '26',
        '31',
        '38',
        '53',
        '60',
        'D2',
        'G8',
        'G9',
        '03-53',
        '53-19'
      )

    AttestedChildOfCaretakerCode =
      Types::Coercible::String.enum('YesCovered', 'YesNotCovered', 'No')

    AbsentParentCode = Types::Coercible::String.enum('Yes', 'No', 'Yes-Exempt')

    ParentCaretakerToChildRelationshipCode = RelationshipToTaxFilerCode

    GenderKind = Types::Coercible::String.enum('Male', 'Female')

    DeductionCategoryCode =
      Types::Coercible::String.enum('Alimony', 'StudentLoanInterest')

    MarketPlaceKinds =
      Types::Coercible::String.enum(
        'aca_individual',
        'aca_shop',
        'aca_congress',
        'individual',
        'cover_all',
        'group',
        'fehb',
        'medicaid'
      )

    ProductKind =
      Types::Coercible::String.enum(
        'health_catastrophic',
        'health',
        'dental',
        'life',
        'short_term_disability',
        'long_term_disability',
        'annuities',
        'chip',
        'snap',
        'tanf'
      )

    ProductKinds =
      Types::Coercible::String.enum('health_catastrophic', 'health', 'dental')

    DocumentRights = Types::Coercible::String.enum('public', 'pii_restricted')

    ServiceMarketKind =
      Types::Coercible::String.enum('shop', 'individual', 'coverall')

    GaState = Types::Coercible::String.enum('active', 'incactive')

    IdKey = Types::Coercible::String.enum('curam_e_case_id')

    IdentifierKindKey = Types::Coercible::String.enum('e_case')

    IdentifierKindNamespace = Types::Coercible::String.enum('curam')

    PremiumCreditStrategyKinds =
      Types::Coercible::String.enum(
        'unassisted',
        'employer_fixed_cost',
        'employee_fixed_cost',
        'allocated_lump_sum_credit',
        'percentage_contribution',
        'indexed_percentage_contribution',
        'federal_employee_health_benefit'
      )

    BrokerMarketKind =
      Types::Coercible::String.enum('individual', 'shop', 'both')

    GeneralAgencyMarketKinds =
      Types::Coercible::String.enum('individual', 'shop', 'both')

    ProviderKinds = Types::Coercible::String.enum('broker', 'assister')

    EmailKind = Types::Coercible::String.enum('home', 'work')

    AddressKinds =
      Types::Coercible::String.enum(
        'home',
        'work',
        'mailing',
        'primary',
        'mailing',
        'branch'
      )

    PhoneKind =
      Types::Coercible::String.enum(
        'home',
        'work',
        'mobile',
        'main',
        'fax',
        'phone',
        'main'
      )

    EligibilitySourceKinds =
      Types::Coercible::String.enum('Curam', 'Admin', 'Renewals', 'Faa', 'Ffe')

    EligibilityCsrKinds =
      Types::Coercible::String.enum(
        'csr_100',
        'csr_94',
        'csr_87',
        'csr_73',
        'csr_0',
        'csr_limited'
      )

    EnrollmentKind =
      Types::Coercible::String.enum('open_enrollment', 'special_enrollment')

    EnrollmentMarketPlaceKind =
      Types::Coercible::String.enum(
        'individual',
        'employer_sponsored',
        'employer_sponsored_cobra',
        'coverall',
        'unassisted_qhp',
        'insurance_assisted_qhp',
        'streamlined_medicaid',
        'emergency_medicaid',
        'hcr_chip'
      )

    EnrollmentExemptionKinds =
      Types::Coercible::String.enum(
        'hardship',
        'health_care_ministry_member',
        'incarceration',
        'indian_tribe_member',
        'religious_conscience'
      )

    MarketTransitionRoleTypes =
      Types::Coercible::String.enum('consumer', 'resident')

    MarketTransitionReasonCodes =
      Types::Coercible::String.enum(
        'initial_individual_market_transition_created_using_data_migration',
        'eligibility_failed_or_documents_not_received_by_due_date',
        'eligibility_documents_provided',
        'generating_consumer_role',
        'generating_resident_role'
      )

    ProductsByMarketPlaceKind = {
      aca_individual: %w[health_catastrophic health dental],
      aca_shop: %w[health dental],
      aca_congress: %w[health dental],
      individual: %w[health dental],
      cover_all: %w[health dental],
      group: %w[
        health
        dental
        life
        short_term_disability
        long_term_disability
        annuities
      ],
      fehb: %w[health dental],
      medicaid: %w[chip snap tanf]
    }.freeze

    AddressValidationStatusCode =
      Types::Coercible::String.enum(
        'ValidMatch',
        'PartialMatch',
        'NoStreet',
        'NoCity'
      )

    EmailAddressRegex = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
      .freeze

    EmailAddressKind = Types::String.constrained(format: EmailAddressRegex)

    # Regex for PhoneNumber
    NumbersOnlyRegex = /^[0-9]/.freeze

    ZipCodeRegex = /\A\d{5}(-\d{4})?\z/.freeze

    # List of the documents user can provide to verify Immigration status
    VlpDocumentKind =
      Types::Coercible::String.enum(
        'I-327 (Reentry Permit)',
        'I-551 (Permanent Resident Card)',
        'I-571 (Refugee Travel Document)',
        'I-766 (Employment Authorization Card)',
        'Certificate of Citizenship',
        'Naturalization Certificate',
        'Machine Readable Immigrant Visa (with Temporary I-551 Language)',
        'Temporary I-551 Stamp (on passport or I-94)',
        'I-94 (Arrival/Departure Record)',
        'I-94 (Arrival/Departure Record) in Unexpired Foreign Passport',
        'Unexpired Foreign Passport',
        'I-20 (Certificate of Eligibility for Nonimmigrant (F-1) Student Status)',
        'DS2019 (Certificate of Eligibility for Exchange Visitor (J-1) Status)',
        'Other (With Alien Number)',
        'Other (With I-94 Number)'
      )
  end

  RelayStateKinds = Types::Coercible::String.enum(
    '/exchanges/hbx_profiles',
    '/benefit_sponsors/profiles/registrations/new?portal=true&profile_type=broker_agency',
    '/benefit_sponsors/profiles/broker_agencies/broker_agency_profiles'
  )

  UriKind = Types.Constructor(String) {|value| URI(value) }

  # RelayStateKind = Types.Constructor(String) {|value|
  #   uri = UriKind[value]
  #   path = [uri.path, uri.query].compact.join('?')
  #   RelayStateKinds[path]
  # }

  # rubocop:enable Metrics/ModuleLength
end
