@using Server.Models
@using System.Web
@using Shared.Models
@using Server.Services
@using Server

@inject LocalizationService T
@model HomeIndexViewModel
@{
    ViewData["Title"] = "Home Page";
    bool hasName = User.Identity?.Name is not null;
    string name = "";
    if (hasName && User.Identity is not null && User.Identity.Name is not null)
    {
        name = User.Identity.Name;
    }
}

<div class="container py-4">
    <h1 class="visually-hidden">Searchdomains</h1>
    <p class="mb-4 fs-3">
        @(hasName ? T["Hi, {0}!", name] : T["Hi!"])
    </p>

    <div class="row g-4">

        <!-- Server -->
        <div class="col-md-6">
            <div class="card shadow-sm h-100">
                <div class="card-body">
                    <h2 class="card-title fs-5">@T["Server"]</h2>

                    <div class="d-flex justify-content-between mt-2">
                        <span>@T["Total RAM usage"]</span>
                        <strong id="serverMemorySize"></strong>
                    </div>
                    <div class="d-flex justify-content-between mt-2">
                        <span>@T["Total Database size"]</span>
                        <strong id="serverDatabaseSize"></strong>
                    </div>
                </div>
            </div>
        </div>

        <!-- Embedding Cache -->
        <div class="col-md-6">
            <div class="card shadow-sm h-100">
                <div class="card-body">
                    <h2 class="card-title fs-5">@T["Embedding Cache"]</h2>

                    <div class="d-flex justify-content-between">
                        <span>@T["Size"]</span>
                        <strong id="embeddingcacheSize"></strong>
                    </div>

                    <div class="d-flex justify-content-between mt-2">
                        <span>
                            @T["Strings"]
                            <i class="bi bi-info-circle-fill text-info" 
                            data-bs-toggle="tooltip" 
                            title="@T["stringsCountInfo"]"></i>
                        </span>
                        <strong id="embeddingcacheElementCount"></strong>
                    </div>

                    <div class="progress mt-3" style="height: 8px;">
                        <div id="embeddingcacheElementCountProgressBar" class="progress-bar"
                             style="width: 0.00%"></div>
                    </div>

                    <div class="d-flex justify-content-between mt-2">
                        <span>@T["Embeddings"]</span>
                        <strong id="embeddingcacheEmbeddingCount"></strong>
                    </div>
                </div>
            </div>
        </div>

        <!-- Health Checks -->
        <div class="col-md-6">
            <div class="card shadow-sm h-100">
                <div class="card-body">
                    <h2 class="card-title fs-5">@T["Health Checks"]</h2>

                    <ul class="list-group list-group-flush">
                        <li class="list-group-item d-flex justify-content-between">
                            <span>@T["Server"]</span>
                            <span id="healthchecksServer"
                                  class="badge bg-warning">
                                ???????
                            </span>
                        </li>
                        <li class="list-group-item d-flex justify-content-between">
                            <span>@T["AI Providers"]</span>
                            <span id="healthchecksAiProvider"
                                  class="badge bg-warning">
                                ???????
                            </span>
                        </li>
                    </ul>
                </div>
            </div>
        </div>

        <!-- Searchdomains -->
        <div class="col-md-6">
            <div class="card shadow-sm h-100">
                <div class="card-body">
                    <h2 class="card-title fs-5">@T["Searchdomains"]</h2>

                    <div class="d-flex justify-content-between">
                        <span>@T["Count"]</span>
                        <strong id="searchdomainCount"></strong>
                    </div>

                    <div class="d-flex justify-content-between mt-2">
                        <span>@T["Total Entities"]</span>
                        <strong id="searchdomainEntityCount"></strong>
                    </div>

                    <div class="d-flex justify-content-between mt-2">
                        <span>@T["Total query cache utilization"]</span>
                        <strong id="totalQuerycacheUtilization"></strong>
                    </div>

                    <!-- Query cache -->
                    <div class="d-flex justify-content-between mt-2">
                        <span>@T["Query cache entry count"]</span>
                        <strong id="querycacheCount"></strong>
                    </div>

                    <div class="d-flex justify-content-between mt-2">
                        <span>
                            @T["Query cache capacity (loaded)"]
                            <i class="bi bi-info-circle-fill text-info" 
                            data-bs-toggle="tooltip" 
                            title="@T["queryCacheEntryCountLoadedInfo"]"></i>
                        </span>
                        <strong id="querycacheLoadedMaxElementCount"></strong>
                    </div>

                    <div class="progress mt-3" style="height: 8px;">
                        <div id="querycacheLoadedMaxElementCountProgressBar" class="progress-bar"
                             style="width: 0.00%"></div>
                    </div>


                    <div class="d-flex justify-content-between mt-2">
                        <span>
                            @T["Query cache capacity (all)"]
                            <i class="bi bi-info-circle-fill text-info" 
                            data-bs-toggle="tooltip" 
                            title="@T["queryCacheEntryCountAllInfo"]"></i>
                        </span>
                        <strong id="querycacheMaxElementCount"></strong>
                    </div>

                    <div class="progress mt-3" style="height: 8px;">
                        <div id="querycacheMaxElementCountProgressBar" class="progress-bar"
                             style="width: 0.00%"></div>
                    </div>
                </div>
            </div>
        </div>

    </div>
</div>

<script>
    var searchdomains = null;

    document.addEventListener('DOMContentLoaded', async () => {
        let searchdomainCount = document.getElementById("searchdomainCount");
        showThrobber(searchdomainCount);
        let searchdomainEntityCount = document.getElementById("searchdomainEntityCount");
        showThrobber(searchdomainEntityCount);
        let totalQuerycacheUtilization = document.getElementById("totalQuerycacheUtilization");
        showThrobber(totalQuerycacheUtilization);
        let embeddingcacheSize = document.getElementById("embeddingcacheSize");
        showThrobber(embeddingcacheSize);
        let embeddingcacheElementCount = document.getElementById("embeddingcacheElementCount");
        showThrobber(embeddingcacheElementCount);
        let embeddingcacheEmbeddingCount = document.getElementById("embeddingcacheEmbeddingCount");
        showThrobber(embeddingcacheEmbeddingCount);
        let embeddingcacheElementCountProgressBar = document.getElementById("embeddingcacheElementCountProgressBar");

        let querycacheCount = document.getElementById("querycacheCount");
        showThrobber(querycacheCount);
        let querycacheMaxElementCount = document.getElementById("querycacheMaxElementCount");
        showThrobber(querycacheMaxElementCount);
        let querycacheMaxElementCountProgressBar = document.getElementById("querycacheMaxElementCountProgressBar");
        let querycacheLoadedMaxElementCount = document.getElementById("querycacheLoadedMaxElementCount");
        showThrobber(querycacheLoadedMaxElementCount);
        let querycacheLoadedElementCountProgressBar = document.getElementById("querycacheLoadedElementCountProgressBar");

        let serverMemorySize = document.getElementById("serverMemorySize");
        showThrobber(serverMemorySize);
        let serverDatabaseSize = document.getElementById("serverDatabaseSize");
        showThrobber(serverDatabaseSize);

        let healthchecksServer = document.getElementById("healthchecksServer");
        let healthchecksAiProvider = document.getElementById("healthchecksAiProvider");

        (async() => {
            listSearchdomains().then(async result => {
                searchdomains = result.Searchdomains;
                hideThrobber(searchdomainCount);
                searchdomainCount.textContent = searchdomains.length;
            });
            getServerStats().then(result => {
                let utilization = result.EmbeddingCacheUtilization;
                let embeddingCacheMaxElementCount = result.EmbeddingCacheMaxElementCount;
                let embeddingCacheElementCount = result.ElementCount;
                let embeddingCount = result.EmbeddingsCount;
                let entityCount = result.EntityCount;
                let queryCacheUtilization = result.QueryCacheUtilization;
                let queryCacheElementCount = result.QueryCacheElementCount;
                let queryCacheMaxElementCountAll = result.QueryCacheMaxElementCountAll;
                let queryCacheMaxElementCountLoadedSearchdomainsOnly = result.QueryCacheMaxElementCountLoadedSearchdomainsOnly;
                hideThrobber(embeddingcacheSize);
                embeddingcacheSize.textContent = NumberOfBytesAsHumanReadable(utilization);
                hideThrobber(embeddingcacheElementCount);
                embeddingcacheElementCount.textContent = `${embeddingCacheElementCount.toLocaleString()} / ${embeddingCacheMaxElementCount.toLocaleString()}`;
                hideThrobber(embeddingcacheEmbeddingCount);
                embeddingcacheEmbeddingCount.textContent = embeddingCount;
                embeddingcacheElementCountProgressBar.style.width = `${embeddingCacheElementCount / embeddingCacheMaxElementCount * 100}%`;
                hideThrobber(searchdomainEntityCount);
                searchdomainEntityCount.textContent = entityCount;
                hideThrobber(totalQuerycacheUtilization);
                totalQuerycacheUtilization.textContent = NumberOfBytesAsHumanReadable(queryCacheUtilization);
                hideThrobber(querycacheMaxElementCount);
                querycacheCount.textContent = queryCacheElementCount;
                hideThrobber(querycacheCount);
                querycacheMaxElementCount.textContent = queryCacheMaxElementCountAll.toLocaleString();
                querycacheMaxElementCountProgressBar.style.width = `${queryCacheElementCount / queryCacheMaxElementCountAll * 100}%`;
                hideThrobber(querycacheLoadedMaxElementCount);
                querycacheLoadedMaxElementCount.textContent = queryCacheMaxElementCountLoadedSearchdomainsOnly.toLocaleString();
                querycacheLoadedMaxElementCountProgressBar.style.width = `${queryCacheElementCount / queryCacheMaxElementCountLoadedSearchdomainsOnly * 100}%`;
                serverMemorySize.textContent = NumberOfBytesAsHumanReadable(result.RamTotalSize);
                hideThrobber(serverMemorySize);
                serverDatabaseSize.textContent = NumberOfBytesAsHumanReadable(result.DatabaseTotalSize);
                hideThrobber(serverDatabaseSize);
            });
            getHealthCheckStatusAndApply(healthchecksServer, "/healthz/Database");
            getHealthCheckStatusAndApply(healthchecksAiProvider, "/healthz/AIProvider");
        })();
    });


    async function listSearchdomains() {
        return await fetch(`/Searchdomains`)
            .then(r => r.json());
    }

    async function listEntities(searchdomain) {
        return await fetch(`/Entities?searchdomain=${searchdomain}`)
            .then(r => r.json());
    }

    async function getQuerycacheUtilization(searchdomain) {
        return await fetch(`/Searchdomain/QueryCache/Size?searchdomain=${searchdomain}`)
            .then(r => r.json());
    }

    async function getServerStats() {
        return await fetch(`/Server/Stats`)
            .then(r => r.json());
    }

    async function getHealthCheckStatusAndApply(element, url) {
        let text = await fetch(url)
            .then(r => r.text());
        let states = {"Healthy": "bg-success", "Degraded": "bg-warning", "Unhealthy": "bg-danger"};
        for (let state in states) {
            element.classList.remove(states[state]);
        }
        if (states[text]) {
            element.classList.add(states[text]);
        } else {
            element.classList.add("bg-danger");
        }
        element.textContent = text;
    }

    function showThrobber(element = null) {
      if (element == null) element = document;
      element.classList.add('spinner');
    }

    function hideThrobber(element = null) {
      if (element == null) element = document;
      element.classList.remove('spinner');
    }

    function NumberOfBytesAsHumanReadable(bytes, decimals = 2) {
        if (bytes === 0) return '0 B';
        if (bytes > 1.20892581961*(10**27)) return "∞ B";
        const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
        const unitIndex = Math.floor(Math.log2(bytes) / 10);
        const unit = units[Math.min(unitIndex, units.length - 1)];
        const value = bytes / Math.pow(1024, unitIndex);
        
        return `${value.toFixed(decimals)} ${unit}`;
    }

</script>