from core.Constants import Constants
from dataclasses import dataclass, field
from dataclasses_json import dataclass_json, config
from datetime import datetime
from json import JSONDecodeError
from marshmallow import fields
from typing import Optional
from zoneinfo import ZoneInfo
import dataclasses_json
import json
import os


@dataclass_json
@dataclass
class Configuration:
    connection: Optional[str] = field(
        default=None,
        metadata=config(
            undefined=dataclasses_json.Undefined.EXCLUDE,
            exclude=lambda value: value is None
        )
    )
    auto_sync_enabled: Optional[bool] = field(
        default=None,
        metadata=config(
            undefined=dataclasses_json.Undefined.EXCLUDE,
            exclude=lambda value: value is None
        )
    )
    last_synced_at: Optional[datetime] = field(
        default=None,
        metadata=config(
            encoder=lambda datetime_instance: Configuration._iso_format(datetime_instance),
            decoder=lambda datetime_string: Configuration._from_iso_format(datetime_string),
            mm_field=fields.DateTime(format='iso'),
            undefined=dataclasses_json.Undefined.EXCLUDE,
            exclude=lambda value: value is None
        )
    )

    @staticmethod
    def get():

        try:
            config_file_contents = open(f'{Constants.HV_CONFIG_HOME}/config.json', 'r').read()
        except FileNotFoundError:
            return None

        try:
            configuration = json.loads(config_file_contents)
        except JSONDecodeError:
            exit(1)

        # noinspection PyUnresolvedReferences
        configuration = Configuration.from_dict(configuration)

        return configuration

    @staticmethod
    def save(configuration):

        config_file_contents = f'{configuration.to_json(indent=4)}\n'
        os.makedirs(Constants.HV_CONFIG_HOME, exist_ok=True)

        config_file_path = f'{Constants.HV_CONFIG_HOME}/config.json'

        with open(config_file_path, 'w') as config_file:

            config_file.write(config_file_contents)
            config_file.close()

    @staticmethod
    def _iso_format(datetime_instance: datetime):
        datetime_instance = datetime_instance.replace(tzinfo=ZoneInfo('UTC'))
        return datetime.isoformat(datetime_instance).replace('+00:00', 'Z')

    @staticmethod
    def _from_iso_format(datetime_string: str):
        date_string = datetime_string.replace('Z', '+00:00')
        return datetime.fromisoformat(date_string)