from django.conf import settings
from rest_framework import serializers

from intranet.femida.src.api.attachments.serializers import AttachmentSerializer
from intranet.femida.src.api.candidates.serializers import (
    CandidateLiteSerializer,
    CandidateDuplicateWithDetailsSerializer,
)
from intranet.femida.src.api.core.serializers import (
    FemidaSerializer,
    WorkflowActionsField,
    AwareSerializerMixin,
)
from intranet.femida.src.api.references.serializers import (
    ReferenceSerializer,
    ReferenceLiteSerializer,
)
from intranet.femida.src.api.rotations.serializers import RotationSerializer, RotationLiteSerializer
from intranet.femida.src.api.staff.serializers import DepartmentSerializer
from intranet.femida.src.api.users.serializers import UserSerializer
from intranet.femida.src.candidates.choices import (
    SUBMISSION_STATUSES,
    SUBMISSION_SOURCES,
    EXTERNAL_SUBMISSION_SOURCES,
)
from intranet.femida.src.candidates.models import CandidateSubmission
from intranet.femida.src.candidates.submissions.controllers import get_submission_duplicate_triples
from intranet.femida.src.candidates.submissions.helpers import get_submission_vacancies_qs
from intranet.femida.src.candidates.submissions.workflow import SubmissionWorkflow
from intranet.femida.src.publications.models import Publication
from intranet.femida.src.vacancies.models import SubmissionForm, Vacancy


class VacancyForSubmissionSerializer(FemidaSerializer):

    department = DepartmentSerializer()

    class Meta:
        model = Vacancy
        fields = (
            'id',
            'name',
            'status',
            'department',
        )


class SubmissionFormSerializer(FemidaSerializer):

    class Meta:
        model = SubmissionForm
        fields = (
            'id',
            'title',
            'url',
        )


class PublicationAsSubmissionFormSerializer(FemidaSerializer):

    id = serializers.SerializerMethodField()
    url = serializers.ReadOnlyField()

    def __init__(self, *args, id_prefix=None, **kwargs):
        self.id_prefix = id_prefix
        super().__init__(*args, **kwargs)

    def get_id(self, obj):
        if self.id_prefix:
            return f'{self.id_prefix} {obj.id}'
        return obj.id

    class Meta:
        model = Publication
        fields = (
            'id',
            'title',
            'url',
        )


class SubmissionLiteSerializer(FemidaSerializer):

    source = serializers.SerializerMethodField()
    form = serializers.SerializerMethodField()
    reference = ReferenceLiteSerializer()
    rotation = RotationLiteSerializer()
    source_details = serializers.SerializerMethodField()

    def get_source(self, obj):
        if obj.source in EXTERNAL_SUBMISSION_SOURCES:
            return SUBMISSION_SOURCES.form
        return obj.source

    def get_form(self, obj):
        if obj.source == SUBMISSION_SOURCES.form:
            return SubmissionFormSerializer(obj.form).data
        elif obj.source == SUBMISSION_SOURCES.publication:
            return PublicationAsSubmissionFormSerializer(obj.publication, id_prefix='PUB').data

    def get_source_details(self, obj):
        if obj.source == SUBMISSION_SOURCES.form:
            return {
                'title': obj.form.title,
                'url': obj.form.url,
                'status': None,
            }
        elif obj.source == SUBMISSION_SOURCES.publication:
            return {
                'title': obj.publication.title,
                'url': obj.publication.url,
                'status': None,
            }
        elif obj.source == SUBMISSION_SOURCES.reference:
            key = obj.reference.startrek_key or None
            return {
                'title': key,
                'url': settings.STARTREK_URL + key if key else None,
                'status': obj.reference.status,
            }
        elif obj.source == SUBMISSION_SOURCES.rotation:
            key = obj.rotation.startrek_rotation_key or None
            return {
                'title': key,
                'url': settings.STARTREK_URL + key if key else None,
                'status': obj.rotation.status,
            }

    class Meta:
        model = CandidateSubmission
        fields = (
            'id',
            'source',
            'form',
            'reference',
            'rotation',
            'source_details',
            'publication_url',
        )


class SubmissionSerializer(AwareSerializerMixin, SubmissionLiteSerializer):

    candidate = CandidateLiteSerializer()
    responsible = UserSerializer()
    attachment = AttachmentSerializer()

    reference = ReferenceSerializer()
    rotation = RotationSerializer()
    vacancies = serializers.SerializerMethodField()

    parsed_questions = serializers.ReadOnlyField()

    def _get_vacancies(self, obj):
        """
        Возвращает актуальные вакансии для текущего состояния отклика:
        1. если обработанный отклик - вакансии, на которые добавили кандидата при обработке;
        2. если новый отклик - вакансии на объявлении/рекомендации/ротации;
        """
        if obj.status == SUBMISSION_STATUSES.closed:
            return [a.vacancy for a in obj.applications.all()]
        else:
            return get_submission_vacancies_qs(obj)

    def get_vacancies(self, obj):
        return VacancyForSubmissionSerializer(self._get_vacancies(obj), many=True).data

    class Meta(SubmissionLiteSerializer.Meta):
        fields = SubmissionLiteSerializer.Meta.fields + (
            'candidate',
            'created',
            'closed_at',
            'status',
            'responsible',
            'candidate_data',
            'attachment',
            'vacancies',
            'parsed_questions',
        )
        prefetch_related_map = {
            'candidate': ('candidate',),
            'responsible': ('responsible',),
            'attachment': ('attachment',),
            'form': ('form__vacancies',),
            'reference': (
                'reference__vacancies',
                'reference__created_by',
                'reference__processed_by',
            ),
            'rotation': (
                'rotation__vacancies',
                'rotation__created_by',
            ),
            'publication': ('publication',),
            'vacancies': (
                'form__vacancies__department',
                'reference__vacancies__department',
                'applications__vacancy__department',
            ),
        }


class SubmissionDetailSerializer(SubmissionSerializer):

    duplicates = serializers.SerializerMethodField()
    actions = WorkflowActionsField(workflow_class=SubmissionWorkflow)
    candidate_data = serializers.SerializerMethodField()

    def get_duplicates(self, submission):
        duplicate_triples = get_submission_duplicate_triples(submission)
        return [
            CandidateDuplicateWithDetailsSerializer({
                'candidate': candidate,
                'details': info.to_dict(),
            }).data
            for candidate, info, decision in duplicate_triples
        ]

    def get_candidate_data(self, submission):
        return dict(
            submission.candidate_data,
            formatted_cand_info=submission.get_safe_formatted_comment(),
        )

    class Meta(SubmissionSerializer.Meta):
        fields = SubmissionSerializer.Meta.fields + ('duplicates', 'actions')
