/**
 * Страница «Сервисы» на Vue 3 без сборки.
 * Используется runtime-only сборка Vue (без компилятора) и render-функция — совместимо с CSP без unsafe-eval.
 * Подключать после vue.runtime.global.prod.js и vue-i18n.global.prod.js.
 */
(function () {
  'use strict';

  if (typeof Vue === 'undefined' || typeof VueI18n === 'undefined') {
    return;
  }

  var h = Vue.h;

  var apiGet = function (path) {
    var url = path.startsWith('http') ? path : (window.location.origin || '') + path;
    return fetch(url, { credentials: 'same-origin', headers: { Accept: 'application/json' } })
      .then(function (r) { return r.text(); })
      .then(function (text) {
        var data = null;
        try { data = text ? JSON.parse(text) : null; } catch (e) { return { success: false, error: text }; }
        if (data && data.success === false) return { success: false, error: data.error || 'Unknown error' };
        return { success: true, data: data || {} };
      })
      .catch(function (err) { return { success: false, error: err.message || 'Network error' }; });
  };

  var locale = (function () {
    try { return localStorage.getItem('cascad360_admin_locale') || 'ru'; } catch (e) { return 'ru'; }
  })();

  var messages = {
    ru: {
      services: {
        title: 'Управление сервисами',
        filters: 'Фильтры и поиск',
        search_label: 'Поиск по имени',
        search_placeholder: 'Введите имя сервиса...',
        status: 'Статус',
        status_all: 'Все',
        status_healthy: 'Здоровые',
        status_unhealthy: 'Не здоровые',
        status_unknown: 'Неизвестно',
        environment: 'Окружение',
        environment_all: 'Все',
        tags: 'Теги (через запятую)',
        tags_placeholder: 'tag1, tag2...',
        reset_filters: 'Сбросить',
        discovered: 'Обнаруженные сервисы',
        refresh: 'Обновить',
        health_check: 'Проверить здоровье',
        loading: 'Загрузка...',
        empty: 'Сервисы не найдены',
        error: 'Ошибка загрузки сервисов',
        name: 'Имя',
        version: 'Версия',
        env: 'Окружение',
        health: 'Здоровье',
        pagination_prev: 'Назад',
        pagination_next: 'Вперёд',
        pagination_of: 'из',
        pagination_per_page: 'На стр.',
        pagination_range: 'Показано',
        database: 'База данных',
        database_not_configured: 'Не настроена',
        database_configure: 'Настроить',
        database_open_studio: 'Студия'
      }
    },
    en: {
      services: {
        title: 'Services management',
        filters: 'Filters and search',
        search_label: 'Search by name',
        search_placeholder: 'Enter service name...',
        status: 'Status',
        status_all: 'All',
        status_healthy: 'Healthy',
        status_unhealthy: 'Unhealthy',
        status_unknown: 'Unknown',
        environment: 'Environment',
        environment_all: 'All',
        tags: 'Tags (comma-separated)',
        tags_placeholder: 'tag1, tag2...',
        reset_filters: 'Reset',
        discovered: 'Discovered services',
        refresh: 'Refresh',
        health_check: 'Health check',
        loading: 'Loading...',
        empty: 'No services found',
        error: 'Error loading services',
        name: 'Name',
        version: 'Version',
        env: 'Environment',
        health: 'Health',
        pagination_prev: 'Prev',
        pagination_next: 'Next',
        pagination_of: 'of',
        pagination_per_page: 'Per page',
        pagination_range: 'Showing',
        database: 'Database',
        database_not_configured: 'Not configured',
        database_configure: 'Configure',
        database_open_studio: 'Studio'
      }
    }
  };

  var i18n = VueI18n.createI18n({
    legacy: false,
    locale: locale,
    fallbackLocale: 'ru',
    messages: messages
  });

  var mountEl = document.getElementById('app-services');
  if (!mountEl) return;

  var app = Vue.createApp({
    render: function () {
      var self = this;
      var t = this.$t.bind(this);
      var list = this.paginatedList;
      var total = this.filteredList.length;
      var start = this.paginationStart;
      var end = this.paginationEnd;
      var totalPages = this.totalPages;
      var page = this.clampedPage;

      return h('div', { class: 'admin-page admin-services' }, [
        /* Компактная панель: заголовок + фильтры в одну строку */
        h('div', { class: 'admin-toolbar' }, [
          h('h1', { class: 'admin-toolbar__title' }, [
            h('i', { class: 'bi bi-gear-fill', 'aria-hidden': 'true' }),
            t('services.title')
          ]),
          h('div', { class: 'admin-toolbar__filters' }, [
            h('label', { for: 'searchInput', class: 'form-label' }, t('services.search_label')),
            h('input', {
              id: 'searchInput',
              class: 'form-control',
              type: 'text',
              placeholder: t('services.search_placeholder'),
              value: this.filters.search,
              onInput: function (e) { self.filters.search = e.target.value; self.currentPage = 1; }
            }),
            h('label', { for: 'statusFilter', class: 'form-label' }, t('services.status')),
            h('select', {
              id: 'statusFilter',
              class: 'form-select',
              value: this.filters.status,
              onInput: function (e) { self.filters.status = e.target.value; self.currentPage = 1; }
            }, [
              h('option', { value: '' }, t('services.status_all')),
              h('option', { value: 'healthy' }, t('services.status_healthy')),
              h('option', { value: 'unhealthy' }, t('services.status_unhealthy')),
              h('option', { value: 'unknown' }, t('services.status_unknown'))
            ]),
            h('label', { for: 'environmentFilter', class: 'form-label' }, t('services.environment')),
            h('select', {
              id: 'environmentFilter',
              class: 'form-select',
              value: this.filters.environment,
              onInput: function (e) { self.filters.environment = e.target.value; self.currentPage = 1; }
            }, [
              h('option', { value: '' }, t('services.environment_all')),
              h('option', { value: 'production' }, 'Production'),
              h('option', { value: 'staging' }, 'Staging'),
              h('option', { value: 'development' }, 'Development')
            ]),
            h('label', { for: 'tagsFilter', class: 'form-label' }, t('services.tags')),
            h('input', {
              id: 'tagsFilter',
              class: 'form-control',
              type: 'text',
              placeholder: t('services.tags_placeholder'),
              value: this.filters.tags,
              onInput: function (e) { self.filters.tags = e.target.value; self.currentPage = 1; }
            }),
            h('button', {
              type: 'button',
              class: 'btn btn-secondary btn-sm',
              onClick: this.clearFilters
            }, [h('i', { class: 'bi bi-x-circle', 'aria-hidden': 'true' }), ' ' + t('services.reset_filters')])
          ]),
          h('div', { class: 'admin-toolbar__actions' }, [
            h('span', { class: 'badge bg-primary' }, String(total)),
            h('button', {
              type: 'button',
              class: 'btn btn-primary btn-sm',
              disabled: this.loading,
              onClick: this.loadServices
            }, [h('i', { class: 'bi bi-arrow-clockwise', 'aria-hidden': 'true' })]),
            h('button', {
              type: 'button',
              class: 'btn btn-success btn-sm',
              disabled: this.loading,
              onClick: this.loadServices
            }, [h('i', { class: 'bi bi-heart-pulse', 'aria-hidden': 'true' })]),
          ])
        ]),
        /* Таблица с липким заголовком и пагинацией */
        h('div', { class: 'admin-card' }, [
          this.loading
            ? h('div', { class: 'text-center', style: 'padding: 2rem;' }, [
                h('div', { class: 'spinner-border text-primary', role: 'status', 'aria-live': 'polite' }, [
                  h('span', { class: 'visually-hidden' }, t('services.loading'))
                ])
              ])
            : this.error
              ? h('div', { class: 'alert alert-danger m-2', role: 'alert' }, this.error)
              : total === 0
                ? h('div', { class: 'text-muted text-center', style: 'padding: 2rem;' }, t('services.empty'))
                : [
                    h('div', { class: 'admin-table-wrap' }, [
                      h('table', { class: 'admin-table table' }, [
                        h('thead', [
                          h('tr', [
                            h('th', { scope: 'col' }, t('services.name')),
                            h('th', { scope: 'col' }, t('services.version')),
                            h('th', { scope: 'col' }, t('services.env')),
                            h('th', { scope: 'col' }, t('services.health')),
                            h('th', { scope: 'col' }, t('services.database'))
                          ])
                        ]),
                        h('tbody', list.map(function (item) {
                          var binding = self.serviceBindings[item.name];
                          var dbLabel = binding
                            ? (binding.datasource_id + ' / ' + binding.database_name)
                            : t('services.database_not_configured');
                          return h('tr', { key: item.name }, [
                            h('td', item.name),
                            h('td', item.version),
                            h('td', item.environment),
                            h('td', h('span', { class: self.statusBadgeClass(item.status) }, item.status)),
                            h('td', {}, [
                              h('div', { class: 'small text-muted mb-1' }, dbLabel),
                              h('div', { class: 'd-flex gap-1 flex-wrap' }, [
                                h('a', {
                                  class: 'btn btn-sm btn-outline-secondary',
                                  href: '/admin/service-databases?service=' + encodeURIComponent(item.name),
                                  'aria-label': t('services.database_configure') + ' ' + item.name
                                }, t('services.database_configure')),
                                binding ? h('a', {
                                  class: 'btn btn-sm btn-outline-primary',
                                  href: '/admin/db-studio?datasource_id=' + encodeURIComponent(binding.datasource_id) +
                                    '&database=' + encodeURIComponent(binding.database_name),
                                  'aria-label': t('services.database_open_studio') + ' ' + item.name
                                }, t('services.database_open_studio')) : null
                              ])
                            ])
                          ]);
                        }))
                      ])
                    ]),
                    h('div', { class: 'admin-pagination' }, [
                      h('div', { class: 'admin-pagination__info' }, [
                        t('services.pagination_range') + ' ' + start + '–' + end + ' ' + t('services.pagination_of') + ' ' + total
                      ]),
                      h('div', { class: 'admin-pagination__controls' }, [
                        h('label', { class: 'form-label', style: 'margin: 0; margin-right: 4px; font-size: 0.75rem;' }, t('services.pagination_per_page')),
                        h('select', {
                          class: 'form-select',
                          value: String(this.pageSize),
                          onInput: function (e) { self.pageSize = parseInt(e.target.value, 10); self.currentPage = 1; }
                        }, [
                          h('option', { value: '10' }, '10'),
                          h('option', { value: '25' }, '25'),
                          h('option', { value: '50' }, '50'),
                          h('option', { value: '100' }, '100')
                        ]),
                        h('button', {
                          type: 'button',
                          class: 'btn btn-outline-primary btn-sm',
                          disabled: page <= 1,
                          onClick: this.prevPage
                        }, t('services.pagination_prev')),
                        h('span', { style: 'min-width: 4rem; text-align: center;' }, String(page) + ' / ' + String(totalPages)),
                        h('button', {
                          type: 'button',
                          class: 'btn btn-outline-primary btn-sm',
                          disabled: page >= totalPages,
                          onClick: this.nextPage
                        }, t('services.pagination_next'))
                      ])
                    ])
                  ]
        ])
      ]);
    },
    data: function () {
      return {
        loading: true,
        error: null,
        servicesRaw: {},
        serviceBindings: {},
        filters: { search: '', status: '', environment: '', tags: '' },
        currentPage: 1,
        pageSize: 25
      };
    },
    computed: {
      totalPages: function () {
        var n = this.filteredList.length;
        var size = this.pageSize;
        return size > 0 ? Math.max(1, Math.ceil(n / size)) : 1;
      },
      clampedPage: function () {
        return Math.min(Math.max(1, this.currentPage), this.totalPages);
      },
      paginationStart: function () {
        var n = this.filteredList.length;
        if (n === 0) return 0;
        return (this.clampedPage - 1) * this.pageSize + 1;
      },
      paginationEnd: function () {
        var end = this.clampedPage * this.pageSize;
        return Math.min(end, this.filteredList.length);
      },
      paginatedList: function () {
        var list = this.filteredList;
        var start = (this.clampedPage - 1) * this.pageSize;
        return list.slice(start, start + this.pageSize);
      },
      serviceList: function () {
        var raw = this.servicesRaw;
        var list = [];
        for (var name in raw) {
          if (!Object.prototype.hasOwnProperty.call(raw, name)) continue;
          var data = raw[name];
          var metadata = data.metadata || {};
          var endpoints = data.endpoints || [];
          var status = 'unknown';
          if (endpoints.length) {
            var statuses = endpoints.map(function (e) { return (e.health && e.health.status) || 'unknown'; });
            if (statuses.every(function (s) { return s === 'healthy'; })) status = 'healthy';
            else if (statuses.some(function (s) { return s === 'unhealthy'; })) status = 'unhealthy';
          }
          list.push({
            name: name,
            version: metadata.version || '—',
            environment: metadata.environment || '—',
            tags: metadata.tags || [],
            status: status
          });
        }
        return list;
      },
      filteredList: function () {
        var list = this.serviceList;
        var search = (this.filters.search || '').toLowerCase();
        var statusFilter = this.filters.status;
        var envFilter = this.filters.environment;
        var tagsStr = (this.filters.tags || '').trim();
        var filterTags = tagsStr ? tagsStr.split(',').map(function (s) { return s.trim(); }).filter(Boolean) : [];
        return list.filter(function (item) {
          if (search && item.name.toLowerCase().indexOf(search) === -1) return false;
          if (statusFilter && item.status !== statusFilter) return false;
          if (envFilter && item.environment !== envFilter) return false;
          if (filterTags.length && !filterTags.some(function (tag) { return item.tags.indexOf(tag) !== -1; })) return false;
          return true;
        });
      }
    },
    methods: {
      loadServices: function () {
        var self = this;
        this.loading = true;
        this.error = null;
        apiGet('/api/v1/admin/services/list').then(function (result) {
          self.loading = false;
          if (result.success && result.data) {
            self.servicesRaw = result.data.services || {};
          } else {
            self.error = result.error || self.$t('services.error');
          }
        });
        apiGet('/api/v1/admin/databases').then(function (result) {
          var map = {};
          if (result.success && result.data && result.data.databases) {
            result.data.databases.forEach(function (b) {
              if (b.service_name) map[b.service_name] = b;
            });
          }
          self.serviceBindings = map;
        });
      },
      clearFilters: function () {
        this.filters = { search: '', status: '', environment: '', tags: '' };
        this.currentPage = 1;
      },
      setPage: function (p) {
        var tp = this.totalPages;
        if (p >= 1 && p <= tp) this.currentPage = p;
      },
      prevPage: function () {
        if (this.currentPage > 1) this.currentPage--;
      },
      nextPage: function () {
        if (this.currentPage < this.totalPages) this.currentPage++;
      },
      statusBadgeClass: function (status) {
        var map = { healthy: 'badge bg-success', unhealthy: 'badge bg-danger', unknown: 'badge bg-secondary' };
        return map[status] || 'badge bg-secondary';
      }
    },
    mounted: function () {
      this.loadServices();
    }
  });

  app.use(i18n);
  app.mount(mountEl);

  window.addEventListener('admin-locale-changed', function (e) {
    var locale = e.detail && e.detail.locale;
    if (locale && (locale === 'ru' || locale === 'en')) {
      i18n.global.locale.value = locale;
    }
  });
})();
