import { defineStore } from 'pinia';

interface ConversationTokens {
  cumulative_input_tokens: number;
  cumulative_output_tokens: number;
  cumulative_total_tokens: number;
}

interface ProjectStorage {
  used_bytes: number;
  limit_bytes: number | null;
  limit_label: string;
  usage_percent: number | null;
}

interface ContainerSample {
  timestamp: number;
  rx_bytes: number | null;
  tx_bytes: number | null;
}

interface ContainerNetRate {
  down_bps: number | null;
  up_bps: number | null;
}

interface QuotaTier {
  count: number;
  limit: number;
  reset_at: number | null;
  window_start: number | null;
}

interface UsageQuota {
  fast: QuotaTier;
  thinking: QuotaTier;
  search: QuotaTier;
  role: string;
}

const defaultQuotaTier = (): QuotaTier => ({
  count: 0,
  limit: 0,
  reset_at: null,
  window_start: null
});

const buildDefaultQuota = (): UsageQuota => ({
  fast: defaultQuotaTier(),
  thinking: defaultQuotaTier(),
  search: defaultQuotaTier(),
  role: 'user'
});

const PROJECT_STORAGE_POLL_INTERVAL_MS = 60_000;
const PROJECT_STORAGE_POLL_INTERVAL_MAX_MS = 300_000;
const CONTAINER_STATS_POLL_INTERVAL_MS = 5_000;
const CONTAINER_STATS_POLL_INTERVAL_MAX_MS = 30_000;

export const useResourceStore = defineStore('resource', {
  state: () => ({
    tokenPanelCollapsed: true,
    currentContextTokens: 0,
    currentConversationTokens: {
      cumulative_input_tokens: 0,
      cumulative_output_tokens: 0,
      cumulative_total_tokens: 0
    } as ConversationTokens,
    projectStorage: {
      used_bytes: 0,
      limit_bytes: null,
      limit_label: '',
      usage_percent: null
    } as ProjectStorage,
    containerStatus: null as Record<string, any> | null,
    containerNetRate: {
      down_bps: null,
      up_bps: null
    } as ContainerNetRate,
    containerVisibilityBound: false,
    lastContainerSample: null as ContainerSample | null,
    containerStatsInFlight: false,
    containerStatsFailCount: 0,
    containerStatsIntervalMs: CONTAINER_STATS_POLL_INTERVAL_MS,
    containerStatsTimer: null as ReturnType<typeof setInterval> | null,
    projectStorageTimer: null as ReturnType<typeof setInterval> | null,
    projectStorageInFlight: false,
    projectStorageFailCount: 0,
    projectStorageIntervalMs: PROJECT_STORAGE_POLL_INTERVAL_MS,
    usageQuota: buildDefaultQuota(),
    usageQuotaTimer: null as ReturnType<typeof setInterval> | null
  }),
  actions: {
    resetTokenStatistics() {
      this.currentContextTokens = 0;
      this.currentConversationTokens = {
        cumulative_input_tokens: 0,
        cumulative_output_tokens: 0,
        cumulative_total_tokens: 0
      };
    },
    setCurrentContextTokens(value: number) {
      this.currentContextTokens = value || 0;
    },
    toggleTokenPanel() {
      console.log('[UI_DEBUG] toggleTokenPanel called, current state:', this.tokenPanelCollapsed, 'new state:', !this.tokenPanelCollapsed);
      this.tokenPanelCollapsed = !this.tokenPanelCollapsed;
      if (this.tokenPanelCollapsed) {
        this.stopContainerStatsPolling();
      } else {
        this.startContainerStatsPolling();
      }
    },
    async updateCurrentContextTokens(conversationId: string | null) {
      if (!conversationId) {
        this.currentContextTokens = 0;
        return;
      }
      try {
        const response = await fetch(`/api/conversations/${conversationId}/tokens`);
        const data = await response.json();
        if (data.success && data.data) {
          this.currentContextTokens = data.data.total_tokens || 0;
        } else {
          this.currentContextTokens = 0;
        }
      } catch (error) {
        console.warn('获取当前上下文Token异常:', error);
        this.currentContextTokens = 0;
      }
    },
    async fetchConversationTokenStatistics(conversationId: string | null) {
      if (!conversationId) {
        this.resetTokenStatistics();
        return;
      }
      try {
        const response = await fetch(`/api/conversations/${conversationId}/token-statistics`);
        const data = await response.json();
        if (data.success && data.data) {
          this.currentConversationTokens.cumulative_input_tokens =
            data.data.total_input_tokens || 0;
          this.currentConversationTokens.cumulative_output_tokens =
            data.data.total_output_tokens || 0;
          this.currentConversationTokens.cumulative_total_tokens = data.data.total_tokens || 0;
          if (typeof data.data.current_context_tokens === 'number') {
            this.currentContextTokens = data.data.current_context_tokens;
          }
        }
      } catch (error) {
        console.warn('获取Token统计异常:', error);
      }
    },
    applyStatusSnapshot(status: any) {
      if (!status || typeof status !== 'object') {
        return;
      }
      if (status.project) {
        const project = status.project;
        this.projectStorage.used_bytes = project.total_size || 0;
        this.projectStorage.limit_bytes = project.limit_bytes ?? null;
        this.projectStorage.limit_label =
          project.limit_label ||
          (project.limit_bytes
            ? `${(project.limit_bytes / (1024 * 1024)).toFixed(0)} MB`
            : '未限制');
        if (project.limit_bytes) {
          const pct =
            typeof project.usage_percent === 'number'
              ? project.usage_percent
              : (project.total_size / project.limit_bytes) * 100;
          this.projectStorage.usage_percent = pct;
        } else {
          this.projectStorage.usage_percent = null;
        }
      }
      if (Object.prototype.hasOwnProperty.call(status, 'container')) {
        this.updateContainerStatus(status.container);
      }
    },
    updateContainerStatus(status: any) {
      if (!status || status.mode !== 'docker') {
        this.containerStatus = status || null;
        this.containerNetRate = { down_bps: null, up_bps: null };
        this.lastContainerSample = null;
        return;
      }
      const stats = status.stats;
      if (stats && typeof stats.timestamp === 'number') {
        const currentSample: ContainerSample = {
          timestamp: stats.timestamp,
          rx_bytes:
            stats.net_io && typeof stats.net_io.rx_bytes === 'number'
              ? stats.net_io.rx_bytes
              : null,
          tx_bytes:
            stats.net_io && typeof stats.net_io.tx_bytes === 'number' ? stats.net_io.tx_bytes : null
        };
        const last = this.lastContainerSample;
        if (
          last &&
          currentSample.rx_bytes !== null &&
          currentSample.tx_bytes !== null &&
          last.rx_bytes !== null &&
          last.tx_bytes !== null
        ) {
          const deltaT = Math.max(0.001, currentSample.timestamp - last.timestamp);
          const downRate = Math.max(0, (currentSample.rx_bytes - last.rx_bytes) / deltaT);
          const upRate = Math.max(0, (currentSample.tx_bytes - last.tx_bytes) / deltaT);
          this.containerNetRate = {
            down_bps: downRate,
            up_bps: upRate
          };
        } else {
          this.containerNetRate = { down_bps: null, up_bps: null };
        }
        this.lastContainerSample = currentSample;
      } else {
        this.containerNetRate = { down_bps: null, up_bps: null };
        this.lastContainerSample = null;
      }
      this.containerStatus = status;
    },
    async pollContainerStats() {
      if (typeof document !== 'undefined' && document.hidden) {
        return;
      }
      if (this.containerStatsInFlight) {
        return;
      }
      this.containerStatsInFlight = true;
      const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
      const timeoutId = controller ? window.setTimeout(() => controller.abort(), 4000) : null;
      try {
        const response = await fetch('/api/container-status', {
          signal: controller?.signal
        });
        if (!response.ok) {
          throw new Error(`http-${response.status}`);
        }
        const data = await response.json();
        if (data.success) {
          this.updateContainerStatus(data.data || null);
        }
        this.containerStatsFailCount = 0;
        if (this.containerStatsIntervalMs > CONTAINER_STATS_POLL_INTERVAL_MS) {
          this._restartContainerStatsTimer(CONTAINER_STATS_POLL_INTERVAL_MS);
        }
      } catch (error) {
        console.warn('获取容器状态异常:', error);
        this.containerStatsFailCount += 1;
        if (this.containerStatsFailCount >= 3) {
          const nextInterval = Math.min(
            this.containerStatsIntervalMs * 2,
            CONTAINER_STATS_POLL_INTERVAL_MAX_MS
          );
          this._restartContainerStatsTimer(nextInterval);
        }
      } finally {
        this.containerStatsInFlight = false;
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
      }
    },
    startContainerStatsPolling() {
      if (this.containerStatsTimer) {
        return;
      }
      if (this.tokenPanelCollapsed) {
        return;
      }
      this.containerStatsFailCount = 0;
      this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS;
      this.pollContainerStats();
      this.containerStatsTimer = setInterval(() => {
        this.pollContainerStats();
      }, this.containerStatsIntervalMs);
    },
    stopContainerStatsPolling() {
      if (this.containerStatsTimer) {
        clearInterval(this.containerStatsTimer);
        this.containerStatsTimer = null;
      }
      this.containerStatsInFlight = false;
    },
    _restartContainerStatsTimer(interval: number) {
      if (this.containerStatsTimer) {
        clearInterval(this.containerStatsTimer);
        this.containerStatsTimer = null;
      }
      this.containerStatsIntervalMs = interval;
      this.containerStatsTimer = setInterval(() => {
        this.pollContainerStats();
      }, this.containerStatsIntervalMs);
    },
    bindContainerVisibilityWatcher() {
      if (this.containerVisibilityBound || typeof document === 'undefined') {
        return;
      }
      const handler = () => {
        if (document.hidden) {
          this.stopContainerStatsPolling();
        } else {
          this.containerStatsFailCount = 0;
          this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS;
          this.startContainerStatsPolling();
        }
      };
      document.addEventListener('visibilitychange', handler);
      this.containerVisibilityBound = true;
    },
    async pollProjectStorage() {
      if (this.projectStorageInFlight) {
        return;
      }
      this.projectStorageInFlight = true;
      try {
        const resp = await fetch('/api/project-storage');
        if (!resp.ok) {
          throw new Error(resp.statusText || '请求失败');
        }
        const data = await resp.json();
        if (data && data.success && data.data) {
          this.projectStorage.used_bytes = data.data.used_bytes || 0;
          this.projectStorage.limit_bytes = data.data.limit_bytes ?? null;
          this.projectStorage.limit_label = data.data.limit_label || '';
          this.projectStorage.usage_percent = data.data.usage_percent ?? null;
          this.projectStorageFailCount = 0;
          if (this.projectStorageIntervalMs > PROJECT_STORAGE_POLL_INTERVAL_MS) {
            this._restartProjectStorageTimer(PROJECT_STORAGE_POLL_INTERVAL_MS);
          }
        }
      } catch (err) {
        this.projectStorageFailCount += 1;
        console.warn('获取存储信息失败:', err);
        if (this.projectStorageFailCount >= 3) {
          const slower = Math.min(
            this.projectStorageIntervalMs * 2,
            PROJECT_STORAGE_POLL_INTERVAL_MAX_MS
          );
          if (slower !== this.projectStorageIntervalMs) {
            console.warn(`连续获取失败，存储轮询间隔调整为 ${Math.round(slower / 1000)} 秒`);
            this._restartProjectStorageTimer(slower);
          }
        }
      } finally {
        this.projectStorageInFlight = false;
      }
    },
    startProjectStoragePolling() {
      if (this.projectStorageTimer) {
        return;
      }
      this.pollProjectStorage();
      this.projectStorageTimer = setInterval(() => {
        this.pollProjectStorage();
      }, this.projectStorageIntervalMs);
    },
    stopProjectStoragePolling() {
      if (this.projectStorageTimer) {
        clearInterval(this.projectStorageTimer);
        this.projectStorageTimer = null;
      }
      this.projectStorageInFlight = false;
      this.projectStorageFailCount = 0;
      this.projectStorageIntervalMs = PROJECT_STORAGE_POLL_INTERVAL_MS;
    },
    _restartProjectStorageTimer(intervalMs: number) {
      if (this.projectStorageTimer) {
        clearInterval(this.projectStorageTimer);
      }
      this.projectStorageIntervalMs = Math.max(intervalMs, 10_000);
      this.projectStorageTimer = setInterval(() => {
        this.pollProjectStorage();
      }, this.projectStorageIntervalMs);
    },
    normalizeUsageQuota(raw: any) {
      const base = buildDefaultQuota();
      const quotas = (raw && raw.quotas) || {};
      const role = quotas.role || (raw && raw.role) || 'user';
      return {
        fast: { ...base.fast, ...(quotas.fast || {}) },
        thinking: { ...base.thinking, ...(quotas.thinking || {}) },
        search: { ...base.search, ...(quotas.search || {}) },
        role
      };
    },
    setUsageQuota(raw: any) {
      this.usageQuota = this.normalizeUsageQuota(raw);
    },
    async fetchUsageQuota() {
      try {
        const response = await fetch('/api/usage');
        if (!response.ok) {
          throw new Error(response.statusText || '请求失败');
        }
        const data = await response.json();
        if (data && data.success && data.data) {
          this.setUsageQuota(data.data);
        }
      } catch (error) {
        console.warn('获取用量配额失败:', error);
      }
    },
    startUsageQuotaPolling() {
      if (this.usageQuotaTimer) {
        return;
      }
      this.fetchUsageQuota();
      this.usageQuotaTimer = setInterval(() => {
        this.fetchUsageQuota();
      }, 60000);
    },
    stopUsageQuotaPolling() {
      if (this.usageQuotaTimer) {
        clearInterval(this.usageQuotaTimer);
        this.usageQuotaTimer = null;
      }
    }
  }
});
