"""ITL JSON export module."""

import getpass
from datetime import datetime
from pathlib import Path

from planetary_coverage.events import EventsDict, EventsList

from ...misc import fmt_datetime
from ...misc.events import flatten_events
from ...misc.export import save_file
from .mapping import EPS_MAPPING_OBS, EPS_MAPPING_PARAMS
from .schema import MAJIS_ITL_SCHEMAS


@flatten_events
def save_itl_json(
    fout: str | Path | None,
    *events: EventsList | EventsDict,
    ref: str | None = None,
    overlap: bool = False,
) -> Path | dict:
    """Save ITL events to a new JSON ITL file.

    Notes
    -----
    By default, ITL blocks must not overlap each other.
    This can be disable with `overlap=True`.

    """
    if ref is not None:
        raise NotImplementedError

    content = {
        'header': get_header(fout),
        'timeline': [fmt_json(event) for event in events],
    }

    for schema in MAJIS_ITL_SCHEMAS:
        schema.validate(content)

    return save_file(fout, content, suffix='.json')


def get_header(fout: str | Path | None = None) -> dict:
    """Get JSON header."""
    return {
        'filename': 'ITL_.json' if fout is None else Path(fout).name,
        'creation_date': fmt_datetime(datetime.now()),
        'author': getpass.getuser(),
    }


EXCLUDED_KEYS = [
    'ITL',
    'PRIME',
]


def fmt_json(event: EventsList | EventsDict) -> dict:
    """Format event to JSON timeline."""
    content, params = {'name': event.key}, {}
    for eps_key, value in event.items():
        if eps_key in EXCLUDED_KEYS:
            continue

        if eps_key in EPS_MAPPING_OBS:
            json_key, fmt = EPS_MAPPING_OBS[eps_key]
            content[json_key] = fmt(value)

        elif eps_key in EPS_MAPPING_PARAMS:
            json_key, fmt = EPS_MAPPING_PARAMS[eps_key]
            params[json_key] = fmt(value)

        else:
            params[eps_key.lower()] = value

    # Add observation type if missing
    if 'type' not in content:
        content['type'] = 'OBSERVATION'

    # Append parameters after the other obs parameters
    content['parameters'] = params

    # Put comment at the end of the block (if present)
    if 'comment' in content:
        content['comment'] = content.pop('comment')

    return content
