from api_fhir_r4.configurations import GeneralConfiguration, R4IdentifierConfig
from api_fhir_r4.converters import BaseFHIRConverter, EnrolmentOfficerPractitionerConverter, ReferenceConverterMixin
from api_fhir_r4.converters.healthFacilityOrganisationConverter import LocationConverter, PersonConverterMixin
from api_fhir_r4.utils import DbManagerUtils
from core.models import Officer
from django.utils.translation import gettext as _
from fhir.resources.R4B.extension import Extension
from fhir.resources.R4B.practitionerrole import PractitionerRole


class EnrolmentOfficerPractitionerRoleConverter(BaseFHIRConverter, PersonConverterMixin, ReferenceConverterMixin):

    @classmethod
    def to_fhir_obj(cls, imis_officer, reference_type=ReferenceConverterMixin.UUID_REFERENCE_TYPE):
        fhir_practitioner_role = PractitionerRole.construct()
        cls.build_fhir_pk(fhir_practitioner_role, imis_officer, reference_type)
        cls.build_fhir_identifiers(fhir_practitioner_role, imis_officer)
        cls.build_fhir_extension(fhir_practitioner_role, imis_officer, reference_type)
        cls.build_fhir_practitioner_reference(fhir_practitioner_role, imis_officer, reference_type)
        cls.build_fhir_location_references(fhir_practitioner_role, imis_officer, reference_type)
        cls.build_fhir_code(fhir_practitioner_role)
        cls.build_fhir_telecom(fhir_practitioner_role, imis_officer)
        return fhir_practitioner_role

    @classmethod
    def to_imis_obj(cls, fhir_practitioner_role, audit_user_id):
        errors = []
        fhir_practitioner_role = PractitionerRole(**fhir_practitioner_role)
        practitioner = fhir_practitioner_role.practitioner
        imis_officer = EnrolmentOfficerPractitionerConverter.get_imis_obj_by_fhir_reference(practitioner, errors)
        location_references = fhir_practitioner_role.location
        if len(location_references)!=1:
            errors.append("Location does not have 1 element")
        else:
            location = cls.get_location_by_reference(location_references[0], errors)
            substitution_officer = None
        if fhir_practitioner_role.extension and len(fhir_practitioner_role.extension) > 0:
            substitution_officer_reference = fhir_practitioner_role.extension[0].valueReference
            substitution_officer = EnrolmentOfficerPractitionerConverter.get_imis_obj_by_fhir_reference(
                substitution_officer_reference,
            )
        if not cls.valid_condition(imis_officer is None, "Practitioner doesn't exists", errors):
            imis_officer.location = location
            if substitution_officer:
                imis_officer.substitution_officer = substitution_officer
        cls.check_errors(errors)
        return imis_officer

    @classmethod
    def get_fhir_code_identifier_type(cls):
        return R4IdentifierConfig.get_fhir_generic_type_code()

    @classmethod
    def get_reference_obj_uuid(cls, imis_officer):
        return imis_officer.uuid

    @classmethod
    def get_reference_obj_id(cls, imis_officer):
        return imis_officer.id

    @classmethod
    def get_reference_obj_code(cls, imis_officer):
        return imis_officer.code

    @classmethod
    def get_fhir_resource_type(cls):
        return PractitionerRole

    @classmethod
    def get_imis_obj_by_fhir_reference(cls, reference, errors=None):
        return DbManagerUtils.get_object_or_none(
            Officer,
            **cls.get_database_query_id_parameteres_from_reference(reference))

        imis_officer_code = cls.get_resource_id_from_reference(reference)
        return DbManagerUtils.get_object_or_none(Officer, code=imis_officer_code)
        return DbManagerUtils.get_object_or_none(
            Officer,
            **cls.get_database_query_id_parameteres_from_reference(reference))


    @classmethod
    def build_fhir_extension(cls, fhir_practitioner_role, imis_officer, reference_type):
        if imis_officer.substitution_officer:
            extension = Extension.construct()
            extension.url = f"{GeneralConfiguration.get_system_base_url()}StructureDefinition/practitioner-role-substitution-reference"

            reference = EnrolmentOfficerPractitionerConverter.build_fhir_resource_reference(
                imis_officer.substitution_officer,
                reference_type=reference_type
            )
            extension.valueReference = reference
            fhir_practitioner_role.extension = [extension]

    @classmethod
    def build_fhir_identifiers(cls, fhir_practitioner_role, imis_officer):
        identifiers = []
        cls.build_all_identifiers(identifiers, imis_officer)
        fhir_practitioner_role.identifier = identifiers

    @classmethod
    def build_fhir_code_identifier(cls, identifiers, imis_officer):
        if imis_officer.code:
            identifier = cls.build_fhir_identifier(imis_officer.code,
                                                   R4IdentifierConfig.get_fhir_identifier_type_system(),
                                                   R4IdentifierConfig.get_fhir_generic_type_code())
            identifiers.append(identifier)

    @classmethod
    def build_fhir_practitioner_reference(cls, fhir_practitioner_role, imis_officer, reference_type):
        fhir_practitioner_role.practitioner = EnrolmentOfficerPractitionerConverter\
            .build_fhir_resource_reference(imis_officer, reference_type=reference_type)

    @classmethod
    def build_fhir_location_references(cls, fhir_practitioner_role, imis_officer, reference_type):
        if imis_officer.location:
            reference = LocationConverter.build_fhir_resource_reference(
                imis_officer.location, reference_type=reference_type)
            fhir_practitioner_role.location = [reference]

    @classmethod
    def get_location_by_reference(cls, location_references, errors):
        return LocationConverter.get_imis_obj_by_fhir_reference(location_references)

    @classmethod
    def get_first_location(cls, location_references):
        return location_references[0]

    @classmethod
    def build_fhir_code(cls, fhir_practitioner_role):
        system = f"{GeneralConfiguration.get_system_base_url()}CodeSystem/practitioner-qualification-type"
        fhir_practitioner_role.code = [cls.build_codeable_concept(
            system=system,
            code="EO",
            display=_("Enrolment Officer")
        )]

    @classmethod
    def build_fhir_telecom(cls, fhir_practitioner_role, imis_officer):
        fhir_practitioner_role.telecom = cls.build_fhir_telecom_for_person(
            phone=imis_officer.phone,
            email=imis_officer.email
        )
