from agenda_culturel.models import Event
import json
from django.utils import timezone

import logging

logger = logging.getLogger(__name__)


class DBImporterEvents:
    def __init__(self, celery_id):
        self.celery_id = celery_id
        self.error_message = ""
        self.user_id = None
        self.init_result_properties()
        self.today = timezone.now().date().isoformat()

    def init_result_properties(self):
        self.event_objects = []
        self.db_event_objects = []
        self.nb_updated = 0
        self.nb_removed = 0
        self.date = None
        self.url = None

    def get_nb_events(self):
        return len(self.event_objects)

    def get_nb_imported_events(self):
        return len(self.db_event_objects)

    def get_nb_updated_events(self):
        return self.nb_updated

    def get_nb_removed_events(self):
        return self.nb_removed

    def import_events(self, json_structure, user_id=None):
        self.init_result_properties()
        self.user_id = user_id

        try:
            structure = json.loads(json_structure)
        except:
            return (False, "JSON file is not correctly structured")

        if len(structure) == 0:
            return (True, "")

        if "header" not in structure:
            return (False, "JSON is not correctly structured: missing header")
        if "events" not in structure:
            return (False, "JSON is not correctly structured: missing events")

        if "url" in structure["header"]:
            self.url = structure["header"]["url"]
        else:
            return (False, "JSON is not correctly structured: missing url in header")

        if "date" in structure["header"]:
            self.date = structure["header"]["date"]

        # get events
        for event in structure["events"]:
            # only process events if they are today or the days after

            if self.event_takes_place_today_or_after(event):
                # set a default "last modified date"
                if "last_modified" not in event and self.date is not None:
                    event["last_modified"] = self.date

                # conversion to Event, and return an error if it failed
                if not self.load_event(event):
                    return (False, self.error_message)
            else:
                logger.warning("Event in the past, will not be imported: {}".format(event))

        # finally save the loaded events in database
        self.save_imported()

        return (True, "")

    def event_takes_place_today_or_after(self, event):
        # not optimal, but will work: import recurrent events even if they come from the past
        if "recurrences" in event:
            return True

        if "start_day" not in event:
            return False

        if event["start_day"] >= self.today:
            return True

        if "end_day" not in event:
            return False

        return event["end_day"] >= self.today

    def save_imported(self):
        self.db_event_objects, self.nb_updated, self.nb_removed = Event.import_events(
            self.event_objects, remove_missing_from_source=self.url, user_id=self.user_id
        )

    def is_valid_event_structure(self, event):
        if "title" not in event:
            self.error_message = (
                "JSON is not correctly structured: one event without title"
            )
            return False
        if "start_day" not in event:
            self.error_message = (
                "JSON is not correctly structured: one event without start_day"
            )
            return False
        return True

    def load_event(self, event):
        if self.is_valid_event_structure(event):
            logger.warning(
                "Valid event: {} {}".format(event["last_modified"], event["title"])
            )
            event_obj = Event.from_structure(event, self.url)
            self.event_objects.append(event_obj)
            return True
        else:
            logger.warning("Not valid event: {}".format(event))
            return False
