# (c) cavaliba.com  - data/api - info.py

"""
/api/info/: instance identity (version, db version, start date, uuid) followed
by an object-count summary across data, user/group/role, configuration, log,
sirene, and status models.

Method inventory: info.
"""

import os

from django.conf import settings
from django.views.decorators.csrf import csrf_exempt

from app_data.api.aaa import start_api
from app_data.group import Group
from app_data.models import DataClass, DataEAV, DataFile, DataInstance, DataRevision, DataSchema
from app_data.registry import registry_get_key
from app_data.role import Role
from app_data.user import User
from app_home.log import DEBUG, log
from app_home.models import CavalibaAPIStat, CavalibaConfiguration, CavalibaLog, DashboardApp
from app_sirene.models import SMSJournal
from app_status.models import StatusRaw, StatusSampleDay, StatusSampleHour
from app_user.models import SirenePermission

from .helper import get_cavctl_version, send_denied, send_response


def _filestore_file_count():
    """Count regular files on disk under settings.CAVALIBA_FILESTORE (0 if the
    directory doesn't exist). Distinct from instance_file (DataFile DB rows) -
    a mismatch between the two indicates orphaned rows or orphaned files."""

    rootdir = str(settings.CAVALIBA_FILESTORE)
    if not os.path.isdir(rootdir):
        return 0
    return sum(1 for entry in os.scandir(rootdir) if entry.is_file())


#  ----------------------------------------------------------------------------
# /api/info/
#  ----------------------------------------------------------------------------
@csrf_exempt
def info(request):
    """Return instance identity (cavaliba_version, cavaliba_db_version, start_date,
    uuid - all from the registry except cavaliba_version, which is the running
    code version - plus cavctl_supported_version) followed by row counts across
    the main models (schema/field/instance/EAV/file/revision, user/group/role/
    permission, configuration/log/apistat/dashboard, sms, status), and
    filestore_file_count (actual files on disk, not the DataFile row count)."""

    aaa_api = start_api(request, permission="p_info")
    if not aaa_api["is_allowed"]:
        return send_denied()

    reply = {}
    reply["cavaliba_version"] = settings.CAVALIBA_VERSION
    reply["cavaliba_db_version"] = registry_get_key(key="DB_VERSION")
    reply["cavctl_supported_version"] = get_cavctl_version()
    reply["start_date"] = registry_get_key(key="LAST_START")
    reply["uuid"] = registry_get_key(key="INSTANCE_UUID")

    reply["schema_count"] = DataClass.objects.count()
    reply["field_count"] = DataSchema.objects.count()
    reply["instance_count"] = DataInstance.objects.count()
    reply["instance_eav"] = DataEAV.objects.count()
    reply["instance_file"] = DataFile.objects.count()
    reply["filestore_file_count"] = _filestore_file_count()
    reply["revision_count"] = DataRevision.objects.count()

    reply["user_count"] = User.count_all()

    reply["group_count"] = Group.count_all()
    reply["role_count"] = Role.count_all()
    reply["permission_count"] = SirenePermission.objects.count()

    reply["configuration_count"] = CavalibaConfiguration.objects.count()
    reply["log_count"] = CavalibaLog.objects.count()
    reply["apistat_count"] = CavalibaAPIStat.objects.count()
    reply["dashboard_count"] = DashboardApp.objects.count()

    reply["smsjournal_count"] = SMSJournal.objects.count()

    reply["status_raw_count"] = StatusRaw.objects.count()
    reply["status_sample_hour_count"] = StatusSampleHour.objects.count()
    reply["status_sample_day_count"] = StatusSampleDay.objects.count()

    log(DEBUG, aaa=aaa_api, app="api", view="info", action="GET", status="OK", data="")

    # NEXT: last housekeeping

    return send_response(request, reply, 200)
