from django.db import transaction
from django.utils import timezone

from intranet.femida.src.candidates.models import CandidateScoring
from intranet.femida.src.core.signals import post_bulk_create
from intranet.femida.src.utils.files import SheetReaderYTAdapter
from intranet.femida.src.yt.base import ScoringUploadResultsYTTable

from .forms import CandidateScoringUploadForm


class CandidateScoringYTUploader:

    validator_class = CandidateScoringUploadForm

    def __init__(self, table, version, scoring_category):
        self.input_table_name = table
        self.version = version
        self.scoring_category = scoring_category
        self.output_table = ScoringUploadResultsYTTable()

    @property
    def reader(self):
        return SheetReaderYTAdapter(self.input_table_name)

    @transaction.atomic
    def upload(self):
        reader = self.reader
        timestamp = timezone.now()

        candidate_scorings = []
        candidate_ids = set()
        output = []
        for i, data in enumerate(reader, 1):
            validator = self.validator_class(data, context={'candidate_ids': candidate_ids})
            if not validator.is_valid():
                errors_data = dict(**data, **validator.errors)
                output.append({
                    'timestamp': timestamp,
                    'message': errors_data,
                })
                continue

            cleaned_data = validator.cleaned_data
            candidate_ids.add(cleaned_data['candidate'].id)
            candidate_scoring = CandidateScoring(
                version=self.version,
                scoring_category_id=self.scoring_category,
                **cleaned_data,
            )
            candidate_scorings.append(candidate_scoring)

        if output:
            self.output_table.write(output, append=True)
            return

        old_candidate_scorings = CandidateScoring.objects.filter(
            scoring_category_id=self.scoring_category,
            version=self.version,
        )
        old_candidate_scorings.delete()

        CandidateScoring.objects.bulk_create(objs=candidate_scorings, batch_size=1000)
        post_bulk_create.send(
            sender=CandidateScoring,
            queryset=candidate_scorings,
        )

        output = [{'timestamp': timestamp, 'message': 'success'}]
        self.output_table.write(output, append=True)
