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

@inject LocalizationService T
@inject AIProvider AIProvider
@model HomeIndexViewModel
@{
    ViewData["Title"] = "Home Page";
    int i = 0;
    string[] probMethods = [.. Enum.GetValues(typeof(ProbMethodEnum)).Cast<ProbMethodEnum>().Select(e => e.ToString())];
    string[] similarityMethods = [.. Enum.GetValues(typeof(SimilarityMethodEnum)).Cast<SimilarityMethodEnum>().Select(e => e.ToString())];
    string[] models = AIProvider.GetModels();
    Dictionary<int, string> domains = [];
    Model.Searchdomains.ForEach(domain =>
    {
        domains[i++] = domain;
    });
}

<div class="container-fluid mt-4">
  <h1 class="visually-hidden">embeddingsearch</h1>
  <div class="row">

    <!-- Sidebar -->
    <div class="col-md-4 sidebar" role="complementary">
      <div class="card">
        <div class="card-body p-2">
          <h2 class="visually-hidden">@T["Searchdomain selection"]</h2>
          <ul class="list-group list-group-flush mb-2" style="max-height: 60vh; overflow-y: auto;">
            @foreach (var domain in domains)
            {
                <li id="sidebar_domain_@(domain.Key)" class="domain-item list-group-item list-group-item-action text-nowrap" style="width: max-content" title="@domain.Value" onclick="selectDomain(@(domain.Key))">
                    @domain.Value
                </li>
            }
          </ul>
          <button id="searchdomainCreate" class="btn btn-primary w-100">@T["Create"]</button>
        </div>
      </div>
    </div>

    <!-- Main Content -->
    <div class="col col-md-8" role="main">

      <div class="card section-card">
        <div class="card-body">
          <h2 class="visually-hidden">@T["Searchdomain information and settings"]</h2>

          <h3 class="visually-hidden">@T["Actions"]</h3>
          <!-- Header -->
          <div class="d-flex justify-content-between align-items-center mb-3">
            <p id="searchdomainName" class="mb-0 text-nowrap overflow-auto fs-3">Searchdomain</p>
            <div class="col-md-3 text-end w-auto">
              <button id="searchdomainRename" class="btn btn-warning btn-sm me-2">@T["Rename"]</button>
              <button id="searchdomainDelete" class="btn btn-danger btn-sm">@T["Delete"]</button>
            </div>
          </div>

          <!-- Settings -->
          <div class="row align-items-center mb-3">
            <h3>@T["Settings"]</h3>
            <div class="col-md-6">
              <input type="checkbox" class="form-check-input" id="searchdomainConfigCacheReconciliation" />
              <label class="form-check-label" for="searchdomainConfigCacheReconciliation">@T["Cache reconciliation"]</label>
            </div>
            <div class="col-md-2 mt-3 mt-md-0">
              <button class="btn btn-warning w-100" id="searchdomainConfigUpdate">@T["Update"]</button>
            </div>
          </div>

          <h3 class="visually-hidden">@T["Search cache"]</h3>
          <!-- Cache -->
          <div class="d-flex align-items-center mb-4">
            <div class="me-3">
              <strong>@T["Search cache utilization"]:</strong> <span id="cacheUtilization">0.00MiB</span>
            </div>
            <button id="cacheClear" class="btn btn-warning btn-sm">@T["Clear"]</button>
          </div>

          <h3 class="visually-hidden">@T["Database size"]</h3>
          <!-- Database size -->
          <div class="d-flex align-items-center mb-4">
            <div class="me-3">
              <strong>@T["Database size"]:</strong> <span id="databaseUtilization">0.00MiB</span>
            </div>
            <button id="cacheClear" class="btn btn-warning btn-sm">@T["Clear"]</button>
          </div>

          <!-- Recent Queries -->
          <div class="card section-card mb-4">
            <div class="card-body">
              <div class="d-flex justify-content-between align-items-center mb-2">
                <h3>Recent queries</h3>
                <input
                  type="text"
                  class="form-control form-control-sm w-25"
                  placeholder="filter"
                />
              </div>
              <div class="spinner d-none"></div>
              <table id="queriesTable" class="table table-striped" style="max-height: 60vh; overflow-y: auto; display: block;">
                <thead>
                  <tr>
                    <th class="visually-hidden">Name</th>
                    <th class="visually-hidden">Action</th>
                  </tr>
                </thead>
                <tbody>
                </tbody>
              </table>
            </div>
          </div>

          <!-- Entities -->
          <div class="card section-card">
            <div class="card-body">
              <div class="d-flex justify-content-between align-items-center mb-2">
                <h3>Entities</h3>
                <input
                  id="entitiesFilter"
                  type="text"
                  class="form-control form-control-sm w-25"
                  placeholder="filter"
                />
              </div>
              <div class="spinner d-none"></div>
              <table id="entitiesTable" class="table table-striped" style="max-height: 60vh; overflow-y: auto; display: block;">
                <thead>
                  <tr>
                    <th class="visually-hidden">Name</th>
                    <th class="visually-hidden">Action</th>
                  </tr>
                </thead>
                <tbody>
                </tbody>
              </table>
              <buttton class="btn btn-primary" id="entityCreate">@T["Add new entity"]</buttton>
            </div>
          </div>

        </div>
      </div>

    </div>
  </div>
</div>

<!-- Entity Details Modal -->
<div class="modal fade" id="entityDetailsModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-lg modal-dialog-scrollable">
    <div class="modal-content">
      <div class="modal-header bg-info">
        <h2 class="modal-title" id="entityDetailsTitle">@T["Entity Details"]</h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <!-- Attributes -->
        <h3 class="fs-4">@T["Attributes"]</h3>
        <table class="table table-sm table-bordered mb-4">
          <thead>
            <tr>
              <th>@T["Key"]</th>
              <th>@T["Value"]</th>
            </tr>
          </thead>
          <tbody id="entityAttributesBody">
          </tbody>
        </table>

        <!-- Datapoints -->
        <h3 class="fs-4">@T["Datapoints"]</h3>
        <table class="table table-sm table-striped">
          <thead>
            <tr>
              <th>@T["Name"]</th>
              <th>@T["ProbMethod"]</th>
              <th>@T["SimilarityMethod"]</th>
            </tr>
          </thead>
          <tbody id="entityDatapointsBody">
          </tbody>
        </table>
      </div>

      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          @T["Close"]
        </button>
      </div>
    </div>
  </div>
</div>

<!-- Query Details Modal -->
<div class="modal fade" id="queryDetailsModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-xl modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header bg-info">
        <h2 class="modal-title" id="queryDetailsTitle">@T["Query Details"] - <span id="queryDetailsQueryName"></span></h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">

        <!-- Access times -->
        <h3>Access times</h3>
        <ul id="queryAccessTimes" class="list-group mb-4"></ul>

        <!-- Results -->
        <h3>Results</h3>
        <table class="table table-sm table-striped">
          <thead>
            <tr>
              <th>Score</th>
              <th>Name</th>
            </tr>
          </thead>
          <tbody id="queryResultsBody"></tbody>
        </table>

      </div>

      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          Close
        </button>
      </div>

    </div>
  </div>
</div>

<!-- Rename searchdomain Modal -->
<div class="modal fade" id="renameSearchdomainModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-m modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header bg-warning">
        <h2 class="modal-title" id="renameSearchdomainTitle">@T["Rename searchdomain"]</h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <!-- New name -->
        <div class="mb-3">
          <label for="renameSearchdomainNewName" class="form-label">New name</label>
          <input type="text" class="form-control" id="renameSearchdomainNewName" />
        </div>
      </div>

      <div class="modal-footer">
        <button type="button" class="btn btn-warning" onclick="renameSearchdomain(getSelectedDomainKey(), document.getElementById('renameSearchdomainNewName').value)" data-bs-dismiss="modal">
          Rename
        </button>
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          Close
        </button>
      </div>
    </div>
  </div>
</div>

<!-- Delete searchdomain Modal -->
<div class="modal fade" id="deleteSearchdomainModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-m modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header bg-danger text-white">
        <h2 class="modal-title" id="deleteSearchdomainTitle">@T["Delete searchdomain"]</h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <p>@Html.Raw(T["GenericDeleteConfirmation", "deleteSearchdomainConfirmationModalName"])</p>
        <p>@T["IrreversibleActionWarning"]</p>
      </div>

      <div class="modal-footer">
        <button type="button" id="searchdomainConfirmDelete" class="btn btn-danger" data-bs-dismiss="modal">
          Delete
        </button>
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          Close
        </button>
      </div>

    </div>
  </div>
</div>

<!-- Create searchdomain Modal -->
<div class="modal fade" id="createSearchdomainModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-m modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header bg-primary text-white">
        <h2 class="modal-title" id="createSearchdomainTitle">@T["Create searchdomain"]</h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <label for="createSearchdomainName" class="form-label">@T["Searchdomain name"]</label>
        <input type="text" class="form-control mb-3" id="createSearchdomainName" placeholder="@T["Searchdomain name"]" />
        <input type="checkbox" class="form-check-input" id="createSearchdomainWithCacheReconciliation" />
        <label class="form-check-label" for="createSearchdomainWithCacheReconciliation">@T["Enable cache reconciliation"]</label>
      </div>

      <div class="modal-footer">
        <button type="button" id="searchdomainConfirmCreate" class="btn btn-primary" data-bs-dismiss="modal">
          @T["Create"]
        </button>
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          @T["Close"]
        </button>
      </div>

    </div>
  </div>
</div>

<!-- Create entity Modal -->
<div class="modal fade" id="createEntityModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-xl modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header bg-primary text-white">
        <h2 class="modal-title" id="createEntityTitle">@T["Create entity"]</h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <!-- Entity base -->
        <div class="row g-3">
          <div class="col-md-6">
            <label for="createEntityName" class="form-label">@T["Entity name"]</label>
            <input type="text" class="form-control mb-3" id="createEntityName" placeholder="@T["Entity name"]" />
          </div>
          <div class="col-md-6">
            <label for="createEntityProbMethod" class="form-label">@T["Probmethod"]</label>
            <input list="probMethods" id="createEntityProbMethod" class="form-control" aria-label="@T["Probmethod"]">
            <datalist id="probMethods">
              @foreach (string probMethod in probMethods)
              {
                <option value=@probMethod>@probMethod</option>
              }
            </datalist>
          </div>
        </div>
        <!-- Attributes -->
        <div class="row g-3">
          <h3 class="fs-5">@T["Attributes"]</h3>
          <table>
            <thead>
              <tr>
                <td>@T["Name"]</td>
                <td>@T["Value"]</td>
                <td class="visually-hidden">@T["Action"]</td>
              </tr>
            </thead>
            <tbody id="createEntityAttributesContainer"></tbody>
          </table>
          <button type="button" id="createEntityAttributesAdd" class="btn btn-primary">@T["Add attribute"]</button>
        </div>
        <!-- Datapoints -->
        <div class="row g-3 mt-3">
          <h3 class="fs-5">@T["Datapoints"]</h3>
          <table>
            <thead>
              <tr>
                <td>@T["Name"]</td>
                <td>@T["Value"]</td>
                <td>@T["Probmethod_embedding"]</td>
                <td>@T["Similarity method"]</td>
                <td>@T["Model"]</td>
                <td class="visually-hidden">@T["Action"]</td>
              </tr>
            </thead>
            <tbody id="createEntityDatapointsContainer"></tbody>
          </table>
          <button type="button" id="createEntityDatapointsAdd" class="btn btn-primary">@T["Add datapoint"]</button>
        </div>
      </div>

      <div class="modal-footer">
        <button type="button" id="EntityConfirmCreate" class="btn btn-primary" data-bs-dismiss="modal">
          @T["Create"]
        </button>
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          @T["Close"]
        </button>
      </div>

    </div>
  </div>
</div>

<!-- Delete entity Modal -->
<div class="modal fade" id="deleteEntityModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-m modal-dialog-scrollable">
    <div class="modal-content">

      <div class="modal-header bg-danger text-white">
        <h2 class="modal-title" id="deleteEntityTitle">@T["Delete entity"]</h2>
        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
      </div>

      <div class="modal-body">
        <p>@Html.Raw(T["GenericDeleteConfirmation", "deleteEntityConfirmationModalName"])</p>
        <p>@T["IrreversibleActionWarning"]</p>
      </div>

      <div class="modal-footer">
        <button type="button" id="EntityConfirmDelete" class="btn btn-danger" data-bs-dismiss="modal">
          @T["Delete"]
        </button>
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
          @T["Close"]
        </button>
      </div>

    </div>
  </div>
</div>

<script>
    var domains = JSON.parse('@Html.Raw(System.Text.Json.JsonSerializer.Serialize(domains))');
    var probMethods = JSON.parse('@Html.Raw(System.Text.Json.JsonSerializer.Serialize(probMethods))');
    var similarityMethods = JSON.parse('@Html.Raw(System.Text.Json.JsonSerializer.Serialize(similarityMethods))');
    var entities = null;
    var queries = null;
    var models = JSON.parse('@Html.Raw(System.Text.Json.JsonSerializer.Serialize(models))');

    document.addEventListener('DOMContentLoaded', () => {
        const filterInput = document.getElementById('entitiesFilter');

        filterInput.addEventListener('input', () => {
            populateEntitiesTable(filterInput.value);
        });
    });

    document.addEventListener('DOMContentLoaded', () => {
        const entitiesFilter = document.getElementById('entitiesFilter');
        entitiesFilter.addEventListener('input', () => {
            populateEntitiesTable(entitiesFilter.value);
        });

        const queriesFilter = document.querySelector(
            '#queriesTable'
        ).closest('.card-body').querySelector('input');

        queriesFilter.addEventListener('input', () => {
            populateQueriesTable(queriesFilter.value);
        });
        selectDomain(0);

        document
            .getElementById('searchdomainRename')
            .addEventListener('click', () => {
                const modal = new bootstrap.Modal(
                    document.getElementById('renameSearchdomainModal')
                );
                // Fill in searchdomain current name
                const domainKey = getSelectedDomainKey();
                document.getElementById(
                    'renameSearchdomainNewName'
                ).value = domains[domainKey];
                modal.show();
            });
        document
            .getElementById('searchdomainDelete')
            .addEventListener('click', () => {
                const modal = new bootstrap.Modal(
                    document.getElementById('deleteSearchdomainModal')
                );
                modal.show();
                let searchdomain = domains[getSelectedDomainKey()];
                let deleteSearchdomainConfirmationModalName = document.getElementById('deleteSearchdomainConfirmationModalName');
                deleteSearchdomainConfirmationModalName.textContent = searchdomain;
            });
        document
            .getElementById('searchdomainConfirmDelete')
            .addEventListener('click', () => {
                const domainKey = getSelectedDomainKey();
                deleteSearchdomain(domainKey);
                selectDomain(0);
            });
        document
            .getElementById('searchdomainConfigUpdate')
            .addEventListener('click', () => {
                const domainKey = getSelectedDomainKey();
                const cacheReconciliation = document.getElementById('searchdomainConfigCacheReconciliation').checked;
                updateSearchdomainConfig(domainKey, { CacheReconciliation: cacheReconciliation});
            });

        document
            .getElementById('searchdomainCreate')
            .addEventListener('click', () => {
                const modal = new bootstrap.Modal(
                    document.getElementById('createSearchdomainModal')
                );
                modal.show();
            });
        
        document
            .getElementById('entityCreate')
            .addEventListener('click', () => {
                const modal = new bootstrap.Modal(
                    document.getElementById('createEntityModal')
                );
                modal.show();
                document.getElementById('createEntityDatapointsAdd').click();
            });

        document
            .getElementById('createEntityAttributesAdd')
            .addEventListener('click', () => {
                var uuid = crypto.randomUUID();
                var entityAttributesContainer = document.getElementById('createEntityAttributesContainer');
                var tr = document.createElement('tr');
                tr.setAttribute('data-uid', uuid);
                var tdKey = document.createElement('td');
                var keyInput = document.createElement('input');
                keyInput.classList.add('form-control')
                keyInput.ariaLabel = '@T["Key"]';
                tdKey.append(keyInput);
                var tdValue = document.createElement('td');
                var ValueInput = document.createElement('textarea');
                ValueInput.classList.add('form-control')                
                ValueInput.ariaLabel = '@T["Value"]';
                tdValue.append(ValueInput);
                var tdAction = document.createElement('td');
                var tdButton = document.createElement('button');
                tdButton.classList.add('btn', 'btn-danger');
                tdButton.textContent = '@T["Remove"]';
                tdButton.ariaLabel = '@T["Remove attribute"]';
                tdAction.append(tdButton);
                tdButton.onclick = function() {
                  tr.remove();
                };
                tr.append(tdKey);
                tr.append(tdValue);
                tr.append(tdAction);
                entityAttributesContainer.append(tr);
            });

        document
            .getElementById('createEntityDatapointsAdd')
            .addEventListener('click', () => {
                var uuid = crypto.randomUUID();
                var enntityDatapointsContainer = document.getElementById('createEntityDatapointsContainer');
                var tr = document.createElement('tr');
                tr.setAttribute('data-uid', uuid);
                var tdName = document.createElement('td');
                var nameInput = document.createElement('input');
                nameInput.classList.add('form-control')
                nameInput.ariaLabel = '@T["Name"]';
                tdName.append(nameInput);
                var tdValue = document.createElement('td');
                var ValueInput = document.createElement('textarea');
                ValueInput.classList.add('form-control')                
                ValueInput.ariaLabel = '@T["Value"]';
                tdValue.append(ValueInput);

                var tdProbmethodEmbedding = document.createElement('td');
                var probMethodSelect = document.createElement('select');
                probMethodSelect.classList.add('probmethod');
                for (i in probMethods)
                {
                    let probMethodSelectElement = document.createElement('option');
                    probMethodSelectElement.value = probMethods[i];
                    probMethodSelectElement.text = probMethods[i];
                    probMethodSelect.append(probMethodSelectElement);
                }
                probMethodSelect.classList.add('form-control')                
                probMethodSelect.ariaLabel = '@T["Probmethod_embedding"]';
                tdProbmethodEmbedding.append(probMethodSelect);

                var tdSimilarityMethod = document.createElement('td');
                var similarityMethodSelect = document.createElement('select');
                similarityMethodSelect.classList.add('similarityMethod');
                for (i in similarityMethods)
                {
                    let similarityMethodSelectElement = document.createElement('option');
                    similarityMethodSelectElement.value = similarityMethods[i];
                    similarityMethodSelectElement.text = similarityMethods[i];
                    similarityMethodSelect.append(similarityMethodSelectElement);
                }
                similarityMethodSelect.classList.add('form-control')                
                similarityMethodSelect.ariaLabel = '@T["Similarity method"]';
                tdSimilarityMethod.append(similarityMethodSelect);

                var tdModel = document.createElement('td');
                var modelSelect = document.createElement('select');
                modelSelect.classList.add('model');
                modelSelect.multiple = true;
                for (i in models)
                {
                    let modelSelectElement = document.createElement('option');
                    modelSelectElement.value = models[i];
                    modelSelectElement.text = models[i];
                    modelSelect.append(modelSelectElement);
                }
                modelSelect.classList.add('form-control')
                modelSelect.ariaLabel = '@T["Probmethod_embedding"]';
                tdModel.append(modelSelect);
                
                
                var tdAction = document.createElement('td');
                var tdButton = document.createElement('button');
                tdButton.classList.add('btn', 'btn-danger');
                tdButton.textContent = '@T["Remove"]';
                tdButton.ariaLabel = '@T["Remove attribute"]';
                tdAction.append(tdButton);
                tdButton.onclick = function() {
                  tr.remove();
                };
                tr.append(tdName);
                tr.append(tdValue);
                tr.append(tdProbmethodEmbedding);
                tr.append(tdSimilarityMethod);
                tr.append(tdModel);
                tr.append(tdAction);
                enntityDatapointsContainer.append(tr);

            });

        document
            .getElementById('EntityConfirmCreate')
            .addEventListener('click', () => {
                var name = document.getElementById('createEntityName').value;
                var probMethod = document.getElementById('createEntityProbMethod').value;
                var attributes = getEntityAttributes();
                var datapoints = getEntityDatapoints();
                var data = [{
                  "name": name,
                  "probmethod": probMethod,
                  "searchdomain": encodeURIComponent(domains[getSelectedDomainKey()]),
                  "attributes": attributes,
                  "datapoints": datapoints
                }];
                // TODO add throbber to indicate loading
                fetch(`/Entity/Index`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(data)
                }).then(async response => {
                    result = await response.json();
                    if (response.ok && result.Success) {
                        // TODO add toast
                        console.log('Entity was created successfully');
                        selectDomain(getSelectedDomainKey());
                    } else {
                        // TODO add toast
                        console.error('Failed to create entity:', result.Message);
                    }
                }).catch(error => {
                    console.error('Error creating entity:', error);
                });

            });

        document
            .getElementById('searchdomainConfirmCreate')
            .addEventListener('click', () => {
                const modal = new bootstrap.Modal(
                    document.getElementById('createSearchdomainModal')
                );
                const name = document.getElementById('createSearchdomainName').value;
                const cacheReconciliation = document.getElementById('createSearchdomainWithCacheReconciliation').checked;
                const settings = { CacheReconciliation: cacheReconciliation };
                // Implement create logic here
                fetch(`/Searchdomain/Create?searchdomain=${encodeURIComponent(name)}&settings=${JSON.stringify(settings)}`, {
                    method: 'GET'
                }).then(response => {
                    if (response.ok) {
                        // TODO add toast
                        console.log('Searchdomain created successfully');
                        // Reload the page to show the new searchdomain
                        location.reload();
                    } else {
                        // TODO add toast
                        console.error('Failed to create searchdomain');
                    }
                }).catch(error => {
                    console.error('Error creating searchdomain:', error);
                });
            });

        document
            .getElementById('cacheClear')
            .addEventListener('click', () => {
                const domainKey = getSelectedDomainKey();
                fetch(`/Searchdomain/ClearSearchCache?searchdomain=${encodeURIComponent(domains[domainKey])}`, {
                    method: 'GET'
                }).then(response => {
                    if (response.ok) {
                        // TODO add toast
                        console.log('Searchdomain cache cleared successfully');
                        // Update cache utilization display
                        document.querySelector('#cacheUtilization').innerText = '0.00MiB';
                    } else {
                        // TODO add toast
                        console.error('Failed to clear searchdomain cache');
                    }
                }).catch(error => {
                    console.error('Error clearing searchdomain cache:', error);
                });
            });

        document
          .getElementById('EntityConfirmDelete')
          .addEventListener('click', () => {
                const domainKey = getSelectedDomainKey();
                const entityName = document.getElementById('EntityConfirmDelete').getAttribute('data-name');
                fetch(`/Entity/Delete?searchdomain=${encodeURIComponent(domains[domainKey])}&entityName=${entityName}`, {
                    method: 'GET'
                }).then(async response => {
                    let result = await response.json();
                    if (response.ok && result.Success) {
                        // TODO add toast
                        console.log('Entity deleted successfully');
                        selectDomain(getSelectedDomainKey());
                    } else {
                        // TODO add toast
                        console.error('Failed to delete entity:', result.Message);
                    }
                }).catch(error => {
                    console.error('Error deleting entity:', error);
                });
          });
    });

    function deleteSearchdomain(domainKey) {
        // Implement delete logic here
        fetch(`/Searchdomain/Delete?searchdomain=${encodeURI(domains[domainKey])}`, {
            method: 'GET'
        }).then(response => {
            if (response.ok) {
                // TODO add toast
                // Remove from sidebar
                var domainItem = document.getElementById('sidebar_domain_' + domainKey);
                domainItem.remove();
                console.log('Searchdomain deleted successfully');
            } else {
                // TODO add toast
                console.error('Failed to delete searchdomain');
            }
        }).catch(error => {
            console.error('Error deleting searchdomain:', error);
        });
    }

    function renameSearchdomain(domainKey, newName) {
        // Implement rename logic here
        fetch(`/Searchdomain/Update?searchdomain=${encodeURI(domains[domainKey])}&newName=${newName}`, {
            method: 'GET'
        }).then(response => {
            if (response.ok) {
                // TODO add toast
                // Update sidebar and header name
                var domainItem = document.getElementById('sidebar_domain_' + domainKey);
                domainItem.innerText = newName;
                document.querySelector('.section-card h3').innerText = newName;
                domains[domainKey] = newName;

                console.log('Searchdomain renamed successfully');
            } else {
                // TODO add toast
                console.error('Failed to rename searchdomain');
            }
        }).catch(error => {
            console.error('Error renaming searchdomain:', error);
        });
    }

    function updateSearchdomainConfig(domainKey, newSettings) {
        // Implement update logic here
        fetch(`/Searchdomain/UpdateSettings?searchdomain=${encodeURIComponent(domains[domainKey])}`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(newSettings)
        }).then(response => {
            if (response.ok) {
                // TODO add toast
                console.log('Searchdomain settings updated successfully');
            } else {
                // TODO add toast
                console.error('Failed to update searchdomain settings');
            }
        }).catch(error => {
            console.error('Error updating searchdomain settings:', error);
        });
    }

    function getSelectedDomainKey() {
        return document.querySelector('.domain-item.active').id.split("_")[2] - 0;
    }

    function getSearchdomainConfig(domainKey) {
        return fetch(`/Searchdomain/GetSettings?searchdomain=${encodeURIComponent(domains[domainKey])}`)
            .then(r => r.json());
    }

    function getSearchdomainCacheUtilization(domainKey) {
        return fetch(`/Searchdomain/GetSearchCacheSize?searchdomain=${encodeURIComponent(domains[domainKey])}`)
            .then(r => r.json());
    }

    function getSearchdomainDatabaseUtilization(domainKey) {
        return fetch(`/Searchdomain/GetDatabaseSize?searchdomain=${encodeURIComponent(domains[domainKey])}`)
            .then(r => r.json());
    }

    function selectDomain(domainKey) {
        document.querySelectorAll('.domain-item').forEach(item => {
            item.classList.remove('active');
        });

        var selectedItem = document.getElementById('sidebar_domain_' + domainKey);
        selectedItem.classList.add('active');

        var domainName = domains[domainKey];
        document.querySelector('#searchdomainName').innerText = domainName;

        let searchdomainConfigPromise = getSearchdomainConfig(getSelectedDomainKey());
        let configElementCachereconciliation = document.getElementById('searchdomainConfigCacheReconciliation');

        let cacheUtilizationPromise = getSearchdomainCacheUtilization(getSelectedDomainKey());
        let databaseUtilizationPromise = getSearchdomainDatabaseUtilization(getSelectedDomainKey());

        /* ---------- ENTITIES ---------- */
        let entitiesUrl = `/Entity/List?searchdomain=${encodeURIComponent(domainName)}&returnEmbeddings=false`;
        let entitiesCard = document.querySelector("#entitiesTable").parentElement;
        clearEntitiesTable();
        showEntitiesLoading(entitiesCard);

        fetch(entitiesUrl)
            .then(r => r.json())
            .then(data => {
                entities = data.Results;
                populateEntitiesTable();
                hideEntitiesLoading(entitiesCard);
            })
            .catch(err => {
                console.error(err);
                flagSearchdomainAsErroneous(domainKey);
                hideEntitiesLoading(entitiesCard);
            });

        /* ---------- QUERIES ---------- */
        let queriesUrl = `/Searchdomain/GetSearches?searchdomain=${encodeURIComponent(domainName)}`;
        let queriesCard = document.querySelector("#queriesTable").parentElement;
        clearQueriesTable();
        showQueriesLoading(queriesCard);

        fetch(queriesUrl)
            .then(r => r.json())
            .then(data => {
                queries = Object.entries(data.Searches).map(key => ({"Name": key[0], "AccessDateTimes": key[1].AccessDateTimes, "Results": key[1].Results}));
                populateQueriesTable();
                hideQueriesLoading(queriesCard);
            })
            .catch(err => {
                console.error('Error fetching queries:', err);
                hideQueriesLoading(queriesCard);
            });

        searchdomainConfigPromise.then(searchdomainConfig => {
            if (searchdomainConfig != null && searchdomainConfig.Settings != null)
            {
                console.log(searchdomainConfig);
                configElementCachereconciliation.checked = searchdomainConfig.Settings.CacheReconciliation;
                configElementCachereconciliation.disabled = false;
            } else {
                //configElement.value = 'Error fetching searchdomain config';
                configElementCachereconciliation.disabled = true;
                // TODO add toast
                console.error('Failed to fetch searchdomain config');
            }
        });
        cacheUtilizationPromise.then(cacheUtilization => {
            if (cacheUtilization != null && cacheUtilization.SearchCacheSizeBytes != null)
            {
                document.querySelector('#cacheUtilization').innerText =
                    `${NumberOfBytesAsHumanReadable(cacheUtilization.SearchCacheSizeBytes)}`;
            } else {
                // TODO add toast
                console.error('Failed to fetch searchdomain cache utilization');
            }
        });

        databaseUtilizationPromise.then(databaseUtilization => {
            if (databaseUtilization != null && databaseUtilization.SearchdomainDatabaseSizeBytes != null)
            {
                document.querySelector('#databaseUtilization').innerText =
                    `${NumberOfBytesAsHumanReadable(databaseUtilization.SearchdomainDatabaseSizeBytes)}`;
            } else {
                // TODO add toast
                console.error('Failed to fetch searchdomain database utilization');
            }
        });
    }

    function clearEntitiesTable() {
        var tableBody = document.querySelector('#entitiesTable tbody');
        tableBody.innerHTML = '';
    }

    function clearQueriesTable() {
        document.querySelector('#queriesTable tbody').innerHTML = '';
    }

    function populateEntitiesTable(filterText = '') {
        if (!entities) return;

        var tableBody = document.querySelector('#entitiesTable tbody');
        tableBody.innerHTML = '';

        const normalizedFilter = filterText.toLowerCase();

        let isFirstEntity = true;
        entities
        .filter(e => e.Name.toLowerCase().includes(normalizedFilter))
        .forEach(entity => {
            var row = document.createElement('tr');

            var nameCell = document.createElement('td');
            nameCell.textContent = entity.Name;
            if (isFirstEntity) {
              nameCell.classList.add('w-100'); // Otherwise the table doesn't use the full width
              isFirstEntity = false;
            }
            row.appendChild(nameCell);

            var actionCell = document.createElement('td');
            actionCell.classList.add('btn-group');
            var detailsButton = document.createElement('button');
            detailsButton.className = 'btn btn-info btn-sm';
            detailsButton.textContent = '@T["Details"]';
            detailsButton.setAttribute("data-index", entities.findIndex(en => en == entity));
            detailsButton.addEventListener('click', () => {
              showEntityDetails(entity);
            });

            var updateButton = document.createElement('button');
            updateButton.className = 'btn btn-warning btn-sm';
            updateButton.textContent = '@T["Update"]';
            updateButton.setAttribute("data-index", entities.findIndex(en => en == entity));
            updateButton.addEventListener('click', () => {
              updateEntity(entity);
            });

            var deleteButton = document.createElement('button');
            deleteButton.className = 'btn btn-danger btn-sm';
            deleteButton.textContent = '@T["Delete"]';
            deleteButton.setAttribute("data-index", entities.findIndex(en => en == entity));
            deleteButton.addEventListener('click', () => {
              const modal = new bootstrap.Modal(
                  document.getElementById('deleteEntityModal')
              );
                modal.show();
              let entityConfirmDelete = document.getElementById('EntityConfirmDelete');
              entityConfirmDelete.setAttribute('data-name', entity.Name);
              let deleteEntityConfirmationModalName = document.getElementById('deleteEntityConfirmationModalName');
              deleteEntityConfirmationModalName.textContent = entity.Name;
            });

            actionCell.appendChild(detailsButton);
            actionCell.appendChild(updateButton);
            actionCell.appendChild(deleteButton);
            row.appendChild(actionCell);

            tableBody.appendChild(row);
        });
    }

    function populateQueriesTable(filterText = '') {
        if (!queries) return;


        const tbody = document.querySelector('#queriesTable tbody');
        tbody.innerHTML = '';

        const normalizedFilter = filterText.toLowerCase();

        queries
            .filter(q => q.Name?.toLowerCase().includes(normalizedFilter))
            .forEach(query => {
                const row = document.createElement('tr');

                const nameCell = document.createElement('td');
                nameCell.textContent = query.Name;
                nameCell.classList.add('col-md-12');
                row.appendChild(nameCell);

                const actionCell = document.createElement('td');
                const btn = document.createElement('button');
                btn.className = 'btn btn-sm btn-info';
                btn.textContent = '@T["Details"]';
                btn.addEventListener('click', () => {
                    showQueryDetails(query);
                });

                actionCell.appendChild(btn);
                row.appendChild(actionCell);

                tbody.appendChild(row);
            });



    }

    function flagSearchdomainAsErroneous(domainKey) {
      var domainItem = document.getElementById('sidebar_domain_' + domainKey);
      domainItem.classList.add('list-group-item-danger');
    }

    function showEntitiesLoading(element = null) {
      if (element == null) element = document;
      element.querySelector('.spinner').classList.remove('d-none');
    }

    function hideEntitiesLoading(element = null) {
      if (element == null) element = document;
      element.querySelector('.spinner').classList.add('d-none');
    }

    function showQueriesLoading(element = null) {
        if (!element) element = document;
        element.querySelector('.spinner').classList.remove('d-none');
    }

    function hideQueriesLoading(element = null) {
        if (!element) element = document;
        element.querySelector('.spinner').classList.add('d-none');
    }

    function showEntityDetails(entity) {
      // Title
      document.getElementById('entityDetailsTitle').innerText = entity.Name;

      // Attributes
      const attrBody = document.getElementById('entityAttributesBody');
      attrBody.innerHTML = '';

      const attributes = entity.Attributes || {};
      const attrKeys = Object.keys(attributes);

      if (attrKeys.length === 0) {
          attrBody.innerHTML = `
              <tr>
                <td colspan="2" class="text-muted text-center">No attributes</td>
              </tr>`;
      } else {
          attrKeys.forEach(key => {
              const row = document.createElement('tr');
              attributeKV = attributes[key];
              row.innerHTML = `
                <td>${attributeKV["Name"]}</td>
                <td>${attributeKV["Value"]}</td>
              `;
              attrBody.appendChild(row);
          });
      }

      // Datapoints
      const dpBody = document.getElementById('entityDatapointsBody');
      dpBody.innerHTML = '';

      (entity.Datapoints || []).forEach(dp => {
          const row = document.createElement('tr');
          row.innerHTML = `
            <td>${dp.Name}</td>
            <td>${dp.ProbMethod}</td>
            <td>${dp.SimilarityMethod}</td>
          `;
          dpBody.appendChild(row);
      });

      // Show modal
      const modal = new bootstrap.Modal(
          document.getElementById('entityDetailsModal')
      );
      modal.show();
    }

    function showQueryDetails(query) {
        // Title
        document.getElementById('queryDetailsQueryName').innerText = query.Name;

        /* ---------- Access times ---------- */
        const accessList = document.getElementById('queryAccessTimes');
        accessList.innerHTML = '';

        if (!query.AccessDateTimes || query.AccessDateTimes.length === 0) {
            accessList.innerHTML = `
                <li class="list-group-item text-muted text-center">
                    No access times
                </li>`;
        } else {
            query.AccessDateTimes.forEach(dt => {
                const li = document.createElement('li');
                li.className = 'list-group-item';
                li.textContent = new Date(dt).toLocaleString();
                accessList.appendChild(li);
            });
        }

        /* ---------- Results ---------- */
        const resultsBody = document.getElementById('queryResultsBody');
        resultsBody.innerHTML = '';

        if (!query.Results || query.Results.length === 0) {
            resultsBody.innerHTML = `
                <tr>
                  <td colspan="2" class="text-muted text-center">
                    No results
                  </td>
                </tr>`;
        } else {
            query.Results.forEach(r => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${r.Score.toFixed(4)}</td>
                    <td class="text-break">${r.Name}</td>
                `;
                resultsBody.appendChild(row);
            });
        }

        // Show modal
        const modal = new bootstrap.Modal(
            document.getElementById('queryDetailsModal')
        );
        modal.show();
    }

    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}`;
    }

    function getEntityAttributes(containerName = 'createEntityAttributesContainer') {
        const container = document.getElementById(containerName);
        const rows = container.querySelectorAll('tr[data-uid]');
        const attributes = {};
        
        rows.forEach(row => {
            const keyInput = row.querySelector('input.form-control');
            const valueTextarea = row.querySelector('textarea.form-control');
            
            if (keyInput && valueTextarea) {
                const key = keyInput.value.trim();
                const value = valueTextarea.value.trim();
                
                if (key) {
                    attributes[key] = value;
                }
            }
        });
        
        return attributes;
    }

    function getEntityDatapoints(containerName = 'createEntityDatapointsContainer') {
        const container = document.getElementById(containerName);
        const rows = container.querySelectorAll('tr[data-uid]');
        const datapoints = [];
        
        rows.forEach(row => {
            const keyInput = row.querySelector('input.form-control');
            const valueTextarea = row.querySelector('textarea.form-control');
            const probmethodSelect = row.querySelector('select.probmethod');
            const similaritymethodSelect = row.querySelector('select.similarityMethod');
            const modelSelect = row.querySelector('select.model');
            
            if (keyInput && valueTextarea && probmethodSelect && modelSelect) {
                const key = keyInput.value.trim();
                const value = valueTextarea.value.trim();
                const probMethod = probmethodSelect.selectedOptions[0].value;
                const similarityMethod = similaritymethodSelect.selectedOptions[0].value;
                const modelSelection = Array.from(modelSelect.selectedOptions)
                    .map(option => option.value);
                
                if (key) {
                    let datapoint = {
                      "name": key,
                      "text": value,
                      "probmethod_embedding": probMethod,
                      "similarityMethod": similarityMethod,
                      "model": modelSelection
                    };
                    datapoints.push(datapoint);
                }
            }
        });
        
        return datapoints;
    }

</script>