const PAGE_SIZE_DESKTOP = 6;
const PAGE_SIZE_MOBILE = 4;
const MOBILE_BREAKPOINT = 960;

function getSortOptions() {
  return [
    { value: 'created_desc', label: (window.t && t('sort.created_desc')) || 'Sort: Last created' },
    { value: 'created_asc', label: (window.t && t('sort.created_asc')) || 'Sort: Oldest first' },
    { value: 'name_asc', label: (window.t && t('sort.name_asc')) || 'Sort: Name A–Z' },
    { value: 'name_desc', label: (window.t && t('sort.name_desc')) || 'Sort: Name Z–A' },
  ];
}

function getTabDefs() {
  return [
    { id: 'all', label: (window.t && t('tab.all')) || 'All' },
    { id: 'active', label: (window.t && t('tab.active')) || 'Active' },
    { id: 'draft', label: (window.t && t('tab.draft')) || 'Draft' },
    { id: 'error', label: (window.t && t('tab.error')) || 'Error' },
    { id: 'inactive', label: (window.t && t('tab.inactive')) || 'Inactive' },
  ];
}

function uiStatus(rawStatus) {
  if (rawStatus === 'published') return 'active';
  if (rawStatus === 'archived') return 'inactive';
  if (rawStatus === 'testing') return 'active';
  return rawStatus || 'draft';
}

function currentLocale() {
  return localStorage.getItem('crank_lang') === 'ru' ? 'ru-RU' : 'en-US';
}

function mapOperation(item) {
  var mapped = {
    id: item.id,
    name: item.name,
    display_name: item.display_name,
    protocol: item.protocol,
    status: uiStatus(item.status),
    raw_status: item.status,
    category: item.category || 'general',
    created_at: item.created_at,
    updated_at: item.updated_at,
    published_at: item.published_at,
    target_url: item.target_url || '',
    method: item.target_action || '',
    usage_summary: item.usage_summary || {
      calls_today: 0,
      error_rate_pct: 0,
      avg_latency_ms: 0,
    },
    agent_refs: item.agent_refs || [],
  };

  return window.localizeDemoOperation ? window.localizeDemoOperation(mapped) : mapped;
}

function emptyStats() {
  return {
    total: 0,
    active: 0,
    requestsToday: 0,
    averageLatencyMs: 0,
  };
}

function computeStats(operations) {
  if (!operations.length) return emptyStats();

  var requestsToday = operations.reduce(function(sum, operation) {
    return sum + (operation.usage_summary ? operation.usage_summary.calls_today : 0);
  }, 0);
  var latencyBase = operations.filter(function(operation) {
    return operation.usage_summary && operation.usage_summary.calls_today > 0;
  });
  var latencyWeight = latencyBase.reduce(function(sum, operation) {
    return sum + operation.usage_summary.calls_today;
  }, 0);
  var weightedLatency = latencyBase.reduce(function(sum, operation) {
    return sum + (operation.usage_summary.avg_latency_ms * operation.usage_summary.calls_today);
  }, 0);

  return {
    total: operations.length,
    active: operations.filter(function(operation) { return operation.status === 'active'; }).length,
    requestsToday: requestsToday,
    averageLatencyMs: latencyWeight > 0 ? Math.round(weightedLatency / latencyWeight) : 0,
  };
}

document.addEventListener('alpine:init', function() {
  Alpine.data('catalog', function() {
    return {
      operations: [],
      loading: true,
      loadError: '',
      pageSize: PAGE_SIZE_DESKTOP,
      search: '',
      tab: 'all',
      filterProtocol: null,
      filterCategory: null,
      filterAgent: null,
      sort: 'created_desc',
      page: 1,
      openDropdown: null,
      navOpen: false,
      categoryOptions: [],
      workspaceId: null,
      stats: emptyStats(),
      _opsVersion: 0,
      _nonStatusViewCache: null,
      _nonStatusViewKey: '',
      _filteredCache: null,
      _filteredKey: '',
      _agentsByOpIdCache: null,
      _agentsByOpIdCacheVersion: -1,
      _activeAgentsCache: null,
      _activeAgentsCacheVersion: -1,

      async init() {
        var self = this;

        await (window.whenWorkspacesReady ? window.whenWorkspacesReady() : Promise.resolve());
        var workspace = window.getCurrentWorkspace ? window.getCurrentWorkspace() : null;
        this.workspaceId = workspace ? workspace.id : null;

        var updatePageSize = function() {
          self.pageSize = window.innerWidth <= MOBILE_BREAKPOINT ? PAGE_SIZE_MOBILE : PAGE_SIZE_DESKTOP;
          self.page = 1;
        };

        updatePageSize();
        window.addEventListener('resize', updatePageSize);
        window.addEventListener('crank:langchange', function() {
          self.sort = self.sort;
          applyLang();
        });
        window.addEventListener('crank:workspacechange', async function(event) {
          self.workspaceId = event.detail ? event.detail.id : null;
          await self.reload();
        });
        document.addEventListener('click', function(event) {
          if (!event.target.closest('.filter-dropdown, .sort-dropdown, .user-menu')) {
            self.openDropdown = null;
          }
          if (!event.target.closest('.navbar')) {
            self.navOpen = false;
          }
        });

        await this.reload();
      },

      async reload() {
        this.loading = true;
        this.loadError = '';

        try {
          var response = await window.CrankApi.listOperations(this.workspaceId);
          this.replaceOperations((response && response.items ? response.items : []).map(mapOperation));
          this.categoryOptions = Array.from(new Set(this.operations.map(function(operation) {
            return operation.category;
          }).filter(Boolean))).sort();
          this.stats = computeStats(this.operations);
        } catch (error) {
          this.replaceOperations([]);
          this.categoryOptions = [];
          this.stats = emptyStats();
          this.loadError = error.message || 'Failed to load operations';
        }

        this.loading = false;
        this.page = 1;
      },

      replaceOperations(operations) {
        this.operations = operations;
        this._opsVersion += 1;
        this._nonStatusViewCache = null;
        this._nonStatusViewKey = '';
        this._filteredCache = null;
        this._filteredKey = '';
        this._agentsByOpIdCache = null;
        this._agentsByOpIdCacheVersion = -1;
        this._activeAgentsCache = null;
        this._activeAgentsCacheVersion = -1;
      },

      _applyNonStatusFilters(operations) {
        var filtered = operations;

        if (this.search.trim()) {
          var query = this.search.toLowerCase();
          filtered = filtered.filter(function(operation) {
            return operation.name.toLowerCase().includes(query)
              || operation.display_name.toLowerCase().includes(query)
              || operation.category.toLowerCase().includes(query)
              || (operation.target_url || '').toLowerCase().includes(query);
          });
        }

        if (this.filterProtocol) {
          filtered = filtered.filter(function(operation) { return operation.protocol === this.filterProtocol; }, this);
        }

        if (this.filterCategory) {
          filtered = filtered.filter(function(operation) { return operation.category === this.filterCategory; }, this);
        }

        if (this.filterAgent) {
          filtered = filtered.filter(function(operation) {
            return (operation.agent_refs || []).some(function(agent) { return agent.agent_id === this.filterAgent; }, this);
          }, this);
        }

        return filtered;
      },

      _nonStatusView() {
        var key = [
          this._opsVersion,
          this.search.trim(),
          this.filterProtocol || '',
          this.filterCategory || '',
          this.filterAgent || '',
        ].join('|');

        if (this._nonStatusViewCache && this._nonStatusViewKey === key) {
          return this._nonStatusViewCache;
        }

        var operations = this._applyNonStatusFilters(this.operations);
        var tabCounts = {
          all: operations.length,
          active: 0,
          draft: 0,
          error: 0,
          inactive: 0,
        };

        operations.forEach(function(operation) {
          if (Object.prototype.hasOwnProperty.call(tabCounts, operation.status)) {
            tabCounts[operation.status] += 1;
          }
        });

        this._nonStatusViewKey = key;
        this._nonStatusViewCache = {
          operations: operations,
          tabCounts: tabCounts,
        };
        return this._nonStatusViewCache;
      },

      get filtered() {
        var nonStatusView = this._nonStatusView();
        var key = [
          this._nonStatusViewKey,
          this.tab,
          this.sort,
        ].join('|');

        if (this._filteredCache && this._filteredKey === key) {
          return this._filteredCache;
        }

        var operations = nonStatusView.operations;

        if (this.tab !== 'all') {
          operations = operations.filter(function(operation) {
            return operation.status === this.tab;
          }, this);
        }

        operations = operations.slice().sort(function(left, right) {
          if (this.sort === 'created_desc') return new Date(right.created_at) - new Date(left.created_at);
          if (this.sort === 'created_asc') return new Date(left.created_at) - new Date(right.created_at);
          if (this.sort === 'name_asc') return left.name.localeCompare(right.name);
          if (this.sort === 'name_desc') return right.name.localeCompare(left.name);
          return 0;
        }.bind(this));

        this._filteredKey = key;
        this._filteredCache = operations;
        return this._filteredCache;
      },

      get totalFiltered() {
        return this.filtered.length;
      },

      get totalPages() {
        return Math.max(1, Math.ceil(this.totalFiltered / this.pageSize));
      },

      get paginated() {
        var start = (this.page - 1) * this.pageSize;
        return this.filtered.slice(start, start + this.pageSize);
      },

      get pageStart() {
        return this.totalFiltered === 0 ? 0 : (this.page - 1) * this.pageSize + 1;
      },

      get pageEnd() {
        return Math.min(this.page * this.pageSize, this.totalFiltered);
      },

      tabCount(tab) {
        var tabCounts = this._nonStatusView().tabCounts;
        return Object.prototype.hasOwnProperty.call(tabCounts, tab) ? tabCounts[tab] : 0;
      },

      get activeChips() {
        var chips = [];
        if (this.filterProtocol) chips.push({ key: 'protocol', label: this.tfKey('ops.filter.protocol', { value: this.filterProtocol.toUpperCase() }) });
        if (this.filterCategory) chips.push({ key: 'category', label: this.tfKey('ops.filter.category', { value: this.filterCategory }) });
        if (this.filterAgent) {
          var agent = this.activeAgents.find(function(item) { return item.agent_id === this.filterAgent; }, this);
          chips.push({ key: 'agent', label: this.tfKey('ops.filter.agent', { value: agent ? agent.display_name : '' }) });
        }
        return chips;
      },

      get hasActiveFilters() {
        return !!(this.filterProtocol || this.filterCategory || this.filterAgent || this.search.trim());
      },

      clearChip(key) {
        if (key === 'protocol') this.filterProtocol = null;
        if (key === 'category') this.filterCategory = null;
        if (key === 'agent') this.filterAgent = null;
        this.page = 1;
      },

      clearAllFilters() {
        this.filterProtocol = null;
        this.filterCategory = null;
        this.filterAgent = null;
        this.search = '';
        this.tab = 'all';
        this.page = 1;
      },

      get agentsByOpId() {
        if (this._agentsByOpIdCache && this._agentsByOpIdCacheVersion === this._opsVersion) {
          return this._agentsByOpIdCache;
        }
        var map = {};
        this.operations.forEach(function(operation) {
          map[operation.id] = operation.agent_refs || [];
        });
        this._agentsByOpIdCacheVersion = this._opsVersion;
        this._agentsByOpIdCache = map;
        return this._agentsByOpIdCache;
      },

      get activeAgents() {
        if (this._activeAgentsCache && this._activeAgentsCacheVersion === this._opsVersion) {
          return this._activeAgentsCache;
        }
        var seen = {};
        var agents = [];
        this.operations.forEach(function(operation) {
          (operation.agent_refs || []).forEach(function(agent) {
            if (!seen[agent.agent_id]) {
              seen[agent.agent_id] = true;
              agents.push(agent);
            }
          });
        });
        this._activeAgentsCacheVersion = this._opsVersion;
        this._activeAgentsCache = agents.sort(function(left, right) {
          return left.display_name.localeCompare(right.display_name);
        });
        return this._activeAgentsCache;
      },

      get sortLabel() {
        return getSortOptions().find(function(option) { return option.value === this.sort; }, this)?.label || 'Sort';
      },

      setTab(tab) {
        this.tab = tab;
        this.page = 1;
      },

      setSearch(value) {
        this.search = value;
        this.page = 1;
      },

      setProtocol(value) {
        this.filterProtocol = this.filterProtocol === value ? null : value;
        this.openDropdown = null;
        this.page = 1;
      },

      setCategory(value) {
        this.filterCategory = this.filterCategory === value ? null : value;
        this.openDropdown = null;
        this.page = 1;
      },

      setSort(value) {
        this.sort = value;
        this.openDropdown = null;
      },

      setAgent(value) {
        this.filterAgent = this.filterAgent === value ? null : value;
        this.openDropdown = null;
        this.page = 1;
      },

      clearProtocol() {
        this.filterProtocol = null;
        this.openDropdown = null;
        this.page = 1;
      },

      clearCategory() {
        this.filterCategory = null;
        this.openDropdown = null;
        this.page = 1;
      },

      clearAgent() {
        this.filterAgent = null;
        this.openDropdown = null;
        this.page = 1;
      },

      toggleDropdown(name) {
        this.openDropdown = this.openDropdown === name ? null : name;
      },

      goPage(page) {
        if (page >= 1 && page <= this.totalPages) this.page = page;
      },

      editOperation(operation) {
        window.location.href = ((window.CrankRoutes && window.CrankRoutes.wizard) || '/wizard/')
          + '?mode=edit&operationId=' + encodeURIComponent(operation.id);
      },

      async deleteOperation(id) {
        if (!confirm(this.tKey('ops.delete.confirm'))) return;
        try {
          var operation = this.operations.find(function(item) { return item.id === id; });
          await window.CrankApi.deleteOperation(this.workspaceId, id);
          this.replaceOperations(this.operations.filter(function(operation) { return operation.id !== id; }));
          this.categoryOptions = Array.from(new Set(this.operations.map(function(operation) {
            return operation.category;
          }).filter(Boolean))).sort();
          this.stats = computeStats(this.operations);
          if (window.CrankUi) {
            window.CrankUi.success(
              this.tfKey('ops.delete.success.message', {
                name: operation ? (operation.display_name || operation.name) : ''
              }),
              this.tKey('ops.delete.success.title')
            );
          }
        } catch (error) {
          if (window.CrankUi) {
            window.CrankUi.error(
              error.message || this.tKey('ops.delete.error.message'),
              this.tKey('ops.delete.error.title')
            );
          }
        }
      },

      protocolLabel(operation) {
        if (operation.protocol === 'rest') {
          return operation.method ? ('REST · ' + operation.method) : 'REST';
        }
        if (operation.protocol === 'graphql') return 'GraphQL';
        if (operation.protocol === 'websocket') return 'WebSocket';
        if (operation.protocol === 'soap') return 'SOAP';
        return 'gRPC';
      },

      protocolClass(operation) {
        return 'badge badge-' + operation.protocol;
      },

      statusClass(operation) {
        return 'status-badge status-' + operation.status;
      },

      statusLabel(operation) {
        if (operation.status === 'active') return this.tKey('tab.active');
        if (operation.status === 'inactive') return this.tKey('tab.inactive');
        if (operation.status === 'error') return this.tKey('tab.error');
        return this.tKey('tab.draft');
      },

      formatDate(dateStr) {
        if (!dateStr) return '—';
        return new Date(dateStr).toLocaleDateString(currentLocale(), { month: 'short', day: 'numeric', year: 'numeric' });
      },

      truncateUrl(url) {
        if (!url) return '—';
        return url.length > 42 ? url.slice(0, 42) + '…' : url;
      },

      formatMetricNumber(value) {
        return new Intl.NumberFormat(currentLocale()).format(value || 0);
      },

      tKey(key) {
        return window.t ? t(key) : key;
      },

      tfKey(key, vars) {
        return window.tf ? tf(key, vars) : this.tKey(key);
      },

      get sortOptions() {
        return getSortOptions();
      },

      get tabDefs() {
        return getTabDefs();
      },

      handleNewOperation() {
        window.location.href = (window.CrankRoutes && window.CrankRoutes.wizard) || '/wizard/';
      },

      handleLogout() {
        window.CrankAuth.logout();
      },
    };
  });
});
