"""
What the nightly encrypted backup actually did.

Two different things are called a backup in this panel. The ZIPs listed on the
Backups page are made here, on demand. The nightly job is something else: a
`pg_dump` streamed through gzip into AES-256, written to /root/backups, which
is mode 700 and which the site user cannot read, and correctly so.

That means the panel cannot look at the backups themselves. What it can look
at is the one small file the script writes when it finishes, holding a
timestamp, whether it worked, the size and how many are retained. Nothing that
helps anyone decrypt anything, and no path to the passphrase.

Read, never inferred. A cron line existing proves nothing: the ticket fetcher
had a cron line and had been dead for months.
"""


def nightly_status():
    """
    A dict with label, value, detail and status, ready to render.

    status is one of live, warn, off, matching the colours used elsewhere in
    the panel. Never raises: a broken status file must not take down the page
    that exists to tell you your backups are broken.
    """
    out = {
        'label': 'Unknown',
        'value': 'Not reporting',
        'detail': 'The nightly job has not written a status on this host yet',
        'status': 'off',
        'at': None,
    }
    try:
        import json, os
        from datetime import datetime, timezone
        from django.conf import settings

        path = os.path.join(str(settings.BASE_DIR), 'logs', 'backup-status.json')
        with open(path, encoding='utf-8') as fh:
            raw = json.load(fh)

        when = datetime.strptime(raw['at'], '%Y-%m-%dT%H:%M:%SZ').replace(tzinfo=timezone.utc)
        age_h = (datetime.now(timezone.utc) - when).total_seconds() / 3600
        mb = round((raw.get('bytes') or 0) / 1048576, 1)
        kept = raw.get('kept') or 0
        out['at'] = when

        if raw.get('result') != 'ok':
            out.update({
                'label': 'Failed',
                'status': 'off',
                'value': f'Last attempt failed {when:%d %b %H:%M} UTC',
                'detail': raw.get('note') or 'See /var/log/ft-backup.log',
            })
        elif age_h > 48:
            # Two nights missed. The job is not running, whatever the crontab says.
            out.update({
                'label': 'Stale',
                'status': 'warn',
                'value': f'Last ran {int(age_h // 24)} days ago',
                'detail': f'{when:%d %b %Y %H:%M} UTC, {kept} retained. Nothing since.',
            })
        else:
            out.update({
                'label': 'Healthy',
                'status': 'live',
                'value': f'{when:%d %b %H:%M} UTC, {mb} MB',
                'detail': f'Verified on write. {kept} encrypted backup(s) retained, 30 day rotation.',
            })
    except FileNotFoundError:
        pass
    except Exception as exc:
        out.update({
            'label': 'Unreadable',
            'status': 'off',
            'value': 'Status file will not parse',
            'detail': str(exc)[:120],
        })
    return out
