# Path: osf/models/registration_bulk_upload_job.py
# class JobState(IntEnum):
#     """Defines the six states of registration bulk upload jobs.
#     """
# 
#     PENDING = 0  # Database preparation is in progress
#     INITIALIZED = 1  # Database preparation has been finished and is ready to be picked up
#     PICKED_UP = 2  # Registration creation is in progress
#     DONE_FULL = 3  # All (draft) registrations have been successfully created
#     DONE_PARTIAL = 4  # Some (draft) registrations have failed the creation creation process
#     DONE_ERROR = 5  # All (draft) registrations have failed
# 
# Path: osf/models/registration_bulk_upload_row.py
# class RegistrationBulkUploadContributors:
#     """A helper class of which an instance contains parsed data about contributors per registration row.
#     """
# 
#     def __init__(self, admin_set, read_only_set, read_write_set, author_set, contributor_list):
#         self.contributor_list = contributor_list
#         self.admin_set = admin_set
#         self.read_write_set = read_write_set
#         self.read_only_set = read_only_set
#         self.author_set = author_set
# 
#     def is_bibliographic(self, email):
#         return email in self.author_set
# 
#     def get_permission(self, email):
#         if email in self.admin_set:
#             return ADMIN
#         elif email in self.read_write_set:
#             return WRITE
#         elif email in self.read_only_set:
#             return READ
#         else:
#             raise RegistrationBulkCreationContributorError(error=f'{email} does not have a permission')


import logging
from django.core.exceptions import ValidationError
from django.db.utils import IntegrityError
from django.utils import timezone
from framework import sentry
from framework.auth import Auth
from framework.celery_tasks import app as celery_app
from osf.exceptions import (
    NodeStateError,
    RegistrationBulkCreationContributorError,
    RegistrationBulkCreationRowError,
    UserNotAffiliatedError,
    UserStateError,
    ValidationValueError,
)
from osf.models import (
    AbstractNode,
    Contributor,
    DraftRegistration,
    Institution,
    OSFUser,
    RegistrationBulkUploadJob,
    RegistrationBulkUploadRow,
    RegistrationProvider,
    RegistrationSchema,
    Subject,
)
from osf.models.licenses import NodeLicense
from osf.models.registration_bulk_upload_job import JobState
from osf.models.registration_bulk_upload_row import RegistrationBulkUploadContributors
from osf.registrations.utils import get_registration_provider_submissions_url
from osf.utils.permissions import ADMIN
from website import mails, settings
def set_affiliated_institutions(initiator, draft, affiliated_institutions, row, title, external_id):
    """Set institution affiliations for a given draft.
    """
    for institution in affiliated_institutions:
        try:
            draft.add_affiliated_institution(institution, initiator)
        except UserNotAffiliatedError:
            error = f'Initiator [{initiator._id}] is not affiliated with institution [{institution._id}]'
            raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)


def prepare_contributors(admin_list, read_only_list, read_write_list, author_list, row, title, external_id):
    """Prepare contributors for registration creation. Return a `RegistrationBulkUploadContributors` object.
    """
    if not admin_list:
        error = 'Missing admin contributors'
        raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)
    admin_set = {contributor.get('email') for contributor in admin_list}
    read_write_set = {contributor.get('email') for contributor in read_write_list}
    read_only_set = {contributor.get('email') for contributor in read_only_list}
    if not author_list:
        error = 'Missing bibliographic contributors'
        raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)

    author_set = {contributor.get('email') for contributor in author_list}  # Bibliographic contributors
    contributor_list = admin_list + read_only_list + read_write_list
    contributor_set = set.union(admin_set, read_only_set, read_write_set)  # All contributors
    if not author_set.issubset(contributor_set):
        error = 'Bibliographic contributors must be one of admin, read-only or read-write'
        raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)

# Path: osf/models/registration_bulk_upload_job.py
# class JobState(IntEnum):
#     """Defines the six states of registration bulk upload jobs.
#     """
# 
#     PENDING = 0  # Database preparation is in progress
#     INITIALIZED = 1  # Database preparation has been finished and is ready to be picked up
#     PICKED_UP = 2  # Registration creation is in progress
#     DONE_FULL = 3  # All (draft) registrations have been successfully created
#     DONE_PARTIAL = 4  # Some (draft) registrations have failed the creation creation process
#     DONE_ERROR = 5  # All (draft) registrations have failed
# 
# Path: osf/models/registration_bulk_upload_row.py
# class RegistrationBulkUploadContributors:
#     """A helper class of which an instance contains parsed data about contributors per registration row.
#     """
# 
#     def __init__(self, admin_set, read_only_set, read_write_set, author_set, contributor_list):
#         self.contributor_list = contributor_list
#         self.admin_set = admin_set
#         self.read_write_set = read_write_set
#         self.read_only_set = read_only_set
#         self.author_set = author_set
# 
#     def is_bibliographic(self, email):
#         return email in self.author_set
# 
#     def get_permission(self, email):
#         if email in self.admin_set:
#             return ADMIN
#         elif email in self.read_write_set:
#             return WRITE
#         elif email in self.read_only_set:
#             return READ
#         else:
#             raise RegistrationBulkCreationContributorError(error=f'{email} does not have a permission')


# Path: api/providers/tasks.py
import logging
from django.core.exceptions import ValidationError
from django.db.utils import IntegrityError
from django.utils import timezone
from framework import sentry
from framework.auth import Auth
from framework.celery_tasks import app as celery_app
from osf.exceptions import (
    NodeStateError,
    RegistrationBulkCreationContributorError,
    RegistrationBulkCreationRowError,
    UserNotAffiliatedError,
    UserStateError,
    ValidationValueError,
)
from osf.models import (
    AbstractNode,
    Contributor,
    DraftRegistration,
    Institution,
    OSFUser,
    RegistrationBulkUploadJob,
    RegistrationBulkUploadRow,
    RegistrationProvider,
    RegistrationSchema,
    Subject,
)
from osf.models.licenses import NodeLicense
from osf.models.registration_bulk_upload_job import JobState
from osf.models.registration_bulk_upload_row import RegistrationBulkUploadContributors
from osf.registrations.utils import get_registration_provider_submissions_url
from osf.utils.permissions import ADMIN
from website import mails, settings

def set_affiliated_institutions(initiator, draft, affiliated_institutions, row, title, external_id):
    """Set institution affiliations for a given draft.
    """
    for institution in affiliated_institutions:
        try:
            draft.add_affiliated_institution(institution, initiator)
        except UserNotAffiliatedError:
            error = f'Initiator [{initiator._id}] is not affiliated with institution [{institution._id}]'
            raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)


def prepare_contributors(admin_list, read_only_list, read_write_list, author_list, row, title, external_id):
    """Prepare contributors for registration creation. Return a `RegistrationBulkUploadContributors` object.
    """
    if not admin_list:
        error = 'Missing admin contributors'
        raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)
    admin_set = {contributor.get('email') for contributor in admin_list}
    read_write_set = {contributor.get('email') for contributor in read_write_list}
    read_only_set = {contributor.get('email') for contributor in read_only_list}
    if not author_list:
        error = 'Missing bibliographic contributors'
        raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)

    author_set = {contributor.get('email') for contributor in author_list}  # Bibliographic contributors
    contributor_list = admin_list + read_only_list + read_write_list
    contributor_set = set.union(admin_set, read_only_set, read_write_set)  # All contributors
    if not author_set.issubset(contributor_set):
        error = 'Bibliographic contributors must be one of admin, read-only or read-write'
        raise RegistrationBulkCreationRowError(row.upload.id, row.id, title, external_id, error=error)

    return RegistrationBulkUploadContributors(admin_set, read_only_set, read_write_set, author_set, contributor_list)