<template>
  <layout>
    <div class="bg-white w-full h-full flex flex-col p-[20px] rounded-[16px] overflow-hidden">
      <!-- Header -->
      <TitleSection :title="t('models.title')" :desc="t('models.subtitle')" />

      <!-- Content Area -->
      <div class="flex-1 overflow-y-auto pr-2 pb-10 min-h-0 space-y-12">
        <!-- AI Providers Section -->
        <ProvidersSettings />

        <!-- Token Usage History Section -->
        <div>
          <h2 class="text-2xl font-serif text-[#171717] mb-6 font-normal tracking-tight">
            {{ t('models.recentTokenHistory.title', 'Token Usage History') }}
          </h2>
          
          <div v-if="usageLoading" class="flex items-center justify-center py-12 text-[#99A0AE] bg-gray-50 rounded-2xl border border-transparent border-dashed">
            <el-icon class="is-loading mr-2 text-xl"><Loading /></el-icon>
            {{ t('models.recentTokenHistory.loading', 'Loading usage history...') }}
          </div>
          
          <div v-else-if="visibleUsageHistory.length === 0" class="flex items-center justify-center py-12 text-[#99A0AE] bg-gray-50 rounded-2xl border border-transparent border-dashed">
            {{ t('models.recentTokenHistory.empty', 'No usage history available.') }}
          </div>
          
          <div v-else-if="filteredUsageHistory.length === 0" class="flex items-center justify-center py-12 text-[#99A0AE] bg-gray-50 rounded-2xl border border-transparent border-dashed">
            {{ t('models.recentTokenHistory.emptyForWindow', 'No usage history in the selected time window.') }}
          </div>
          
          <div v-else class="space-y-6">
            <div class="flex flex-wrap items-center justify-between gap-3">
              <div class="flex flex-wrap items-center gap-3">
                <div class="flex rounded-lg bg-gray-100 p-1 border border-gray-200">
                  <el-button
                    :type="usageGroupBy === 'model' ? 'primary' : 'default'"
                    :plain="usageGroupBy !== 'model'"
                    size="small"
                    @click="usageGroupBy = 'model'; usagePage = 1"
                    class="border-0"
                  >
                    {{ t('models.recentTokenHistory.groupByModel', 'By Model') }}
                  </el-button>
                  <el-button
                    :type="usageGroupBy === 'day' ? 'primary' : 'default'"
                    :plain="usageGroupBy !== 'day'"
                    size="small"
                    @click="usageGroupBy = 'day'; usagePage = 1"
                    class="border-0"
                  >
                    {{ t('models.recentTokenHistory.groupByTime', 'By Time') }}
                  </el-button>
                </div>
                <div class="flex rounded-lg bg-gray-100 p-1 border border-gray-200">
                  <el-button
                    :type="usageWindow === '7d' ? 'primary' : 'default'"
                    :plain="usageWindow !== '7d'"
                    size="small"
                    @click="usageWindow = '7d'; usagePage = 1"
                    class="border-0"
                  >
                    {{ t('models.recentTokenHistory.last7Days', 'Last 7 Days') }}
                  </el-button>
                  <el-button
                    :type="usageWindow === '30d' ? 'primary' : 'default'"
                    :plain="usageWindow !== '30d'"
                    size="small"
                    @click="usageWindow = '30d'; usagePage = 1"
                    class="border-0"
                  >
                    {{ t('models.recentTokenHistory.last30Days', 'Last 30 Days') }}
                  </el-button>
                  <el-button
                    :type="usageWindow === 'all' ? 'primary' : 'default'"
                    :plain="usageWindow !== 'all'"
                    size="small"
                    @click="usageWindow = 'all'; usagePage = 1"
                    class="border-0"
                  >
                    {{ t('models.recentTokenHistory.allTime', 'All Time') }}
                  </el-button>
                </div>
              </div>
              <p class="text-[13px] font-medium text-[#99A0AE]">
                {{ usageRefreshing
                  ? t('models.recentTokenHistory.loading', 'Loading...')
                  : t('models.recentTokenHistory.showingLast', `Showing ${filteredUsageHistory.length} records`) }}
              </p>
            </div>

            <UsageBarChart
              :groups="usageGroups"
              :emptyLabel="t('models.recentTokenHistory.empty', 'Empty')"
              :totalLabel="t('models.recentTokenHistory.totalTokens', 'Total')"
              :inputLabel="t('models.recentTokenHistory.inputShort', 'Input')"
              :outputLabel="t('models.recentTokenHistory.outputShort', 'Output')"
              :cacheLabel="t('models.recentTokenHistory.cacheShort', 'Cache')"
            />

            <div class="space-y-3 pt-2">
              <div
                v-for="entry in pagedUsageHistory"
                :key="`${entry.sessionId}-${entry.timestamp}`"
                class="rounded-xl bg-transparent border border-gray-200 p-5 hover:bg-gray-50 transition-colors"
              >
                <div class="flex items-start justify-between gap-3">
                  <div class="min-w-0">
                    <p class="font-semibold text-[15px] text-[#171717] truncate">
                      {{ entry.model || t('models.recentTokenHistory.unknownModel', 'Unknown Model') }}
                    </p>
                    <p class="text-[13px] text-[#99A0AE] truncate mt-0.5">
                      {{ [formatUsageSource(entry.provider), formatUsageSource(entry.agentId), entry.sessionId].filter(Boolean).join(' • ') }}
                    </p>
                  </div>
                  <div class="text-right shrink-0">
                    <p :class="getUsageTotalClass(entry)">
                      {{ formatUsageTotal(entry) }}
                    </p>
                    <p v-if="entry.usageStatus === 'missing'" class="text-[12px] text-[#99A0AE] mt-0.5">
                      {{ t('models.recentTokenHistory.noUsage', 'No usage info') }}
                    </p>
                    <p v-if="entry.usageStatus === 'error'" class="text-[12px] text-red-500 mt-0.5">
                      {{ t('models.recentTokenHistory.usageParseError', 'Error parsing usage') }}
                    </p>
                    <p class="text-[12px] text-[#99A0AE] mt-0.5">
                      {{ formatUsageTimestamp(entry.timestamp) }}
                    </p>
                  </div>
                </div>
                <div class="mt-3 flex flex-wrap gap-x-4 gap-y-1.5 text-[12.5px] font-medium text-[#99A0AE]">
                  <template v-if="entry.usageStatus === 'available' || entry.usageStatus === undefined">
                    <span class="flex items-center gap-1.5"><div class="w-2 h-2 rounded-full bg-sky-500"></div>{{ t('models.recentTokenHistory.input', `Input: ${formatTokenCount(entry.inputTokens)}`) }}</span>
                    <span class="flex items-center gap-1.5"><div class="w-2 h-2 rounded-full bg-violet-500"></div>{{ t('models.recentTokenHistory.output', `Output: ${formatTokenCount(entry.outputTokens)}`) }}</span>
                    <span v-if="entry.cacheReadTokens > 0" class="flex items-center gap-1.5"><div class="w-2 h-2 rounded-full bg-amber-500"></div>{{ t('models.recentTokenHistory.cacheRead', `Cache Read: ${formatTokenCount(entry.cacheReadTokens)}`) }}</span>
                    <span v-if="entry.cacheWriteTokens > 0" class="flex items-center gap-1.5"><div class="w-2 h-2 rounded-full bg-amber-500"></div>{{ t('models.recentTokenHistory.cacheWrite', `Cache Write: ${formatTokenCount(entry.cacheWriteTokens)}`) }}</span>
                  </template>
                  <span v-else class="text-[12px]">
                    {{ entry.usageStatus === 'missing'
                      ? t('models.recentTokenHistory.noUsage', 'No usage reported')
                      : t('models.recentTokenHistory.usageParseError', 'Parse error') }}
                  </span>
                  <span v-if="typeof entry.costUsd === 'number' && Number.isFinite(entry.costUsd)" class="flex items-center gap-1.5 ml-auto text-[#171717] bg-gray-100 px-2 py-0.5 rounded-md">
                    {{ t('models.recentTokenHistory.cost', `$${entry.costUsd.toFixed(4)}`) }}
                  </span>
                  <el-button
                    v-if="devModeUnlocked && entry.content"
                    size="small"
                    class="h-6 rounded-full px-2.5 text-[11.5px] ml-2"
                    @click="selectedUsageEntry = entry"
                  >
                    {{ t('models.recentTokenHistory.viewContent', 'View Content') }}
                  </el-button>
                </div>
              </div>
            </div>

            <div class="flex items-center justify-between gap-3 pt-2">
              <p class="text-[13px] font-medium text-[#99A0AE]">
                {{ t('models.recentTokenHistory.page', `Page ${safeUsagePage} of ${usageTotalPages}`) }}
              </p>
              <div class="flex items-center gap-2">
                <el-button
                  size="small"
                  @click="usagePage = Math.max(1, usagePage - 1)"
                  :disabled="safeUsagePage <= 1"
                  class="rounded-full px-4 h-9"
                >
                  <el-icon class="mr-1"><ArrowLeft /></el-icon>
                  {{ t('models.recentTokenHistory.prev', 'Prev') }}
                </el-button>
                <el-button
                  size="small"
                  @click="usagePage = Math.min(usageTotalPages, usagePage + 1)"
                  :disabled="safeUsagePage >= usageTotalPages"
                  class="rounded-full px-4 h-9"
                >
                  {{ t('models.recentTokenHistory.next', 'Next') }}
                  <el-icon class="ml-1"><ArrowRight /></el-icon>
                </el-button>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Dev Mode Popup -->
      <RequestContentDialog
        v-if="devModeUnlocked && selectedUsageEntry"
        v-model="popupVisible"
        :entry="selectedUsageEntry"
        @closed="selectedUsageEntry = null"
      />
    </div>
  </layout>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import ProvidersSettings from './components/ProvidersSettings.vue';
import UsageBarChart from './components/UsageBarChart.vue';
import RequestContentDialog from './components/RequestContentDialog.vue';
import TitleSection from '@src/components/TitleSection/index.vue'
import { hostApiFetch } from '@lib/host-api';
import {
  filterUsageHistoryByWindow,
  groupUsageHistory,
  resolveStableUsageHistory,
  resolveVisibleUsageHistory,
  type UsageGroupBy,
  type UsageHistoryEntry,
  type UsageWindow,
} from './usage-history';

const { t } = useI18n();

// States
const devModeUnlocked = ref(true); // Default true for now or fetch from a settings store
const usageGroupBy = ref<UsageGroupBy>('model');
const usageWindow = ref<UsageWindow>('7d');
const usagePage = ref(1);
const selectedUsageEntry = ref<UsageHistoryEntry | null>(null);
const popupVisible = computed({
  get: () => selectedUsageEntry.value !== null,
  set: (v) => { if (!v) selectedUsageEntry.value = null; }
});

const fetchState = ref<{
  status: 'idle' | 'loading' | 'done';
  data: UsageHistoryEntry[];
  stableData: UsageHistoryEntry[];
}>({
  status: 'idle',
  data: [],
  stableData: [],
});

const usageLoading = computed(() => fetchState.value.status === 'loading' && visibleUsageHistory.value.length === 0);
const usageRefreshing = computed(() => fetchState.value.status === 'loading' && visibleUsageHistory.value.length > 0);

// Fetching logic
let refreshTimer: ReturnType<typeof setInterval> | null = null;

const fetchUsage = async () => {
  if (fetchState.value.status === 'loading') return;
  fetchState.value.status = 'loading';
  try {
    const entries = await hostApiFetch<UsageHistoryEntry[]>('/api/usage/recent-token-history');
    const normalized = Array.isArray(entries) ? entries : [];
    fetchState.value.stableData = resolveStableUsageHistory(fetchState.value.stableData, normalized);
    fetchState.value.data = normalized;
    fetchState.value.status = 'done';
  } catch (error) {
    console.error('Failed to fetch usage history', error);
    fetchState.value.status = 'done';
  }
};

onMounted(() => {
  fetchUsage();
  refreshTimer = setInterval(fetchUsage, 15000);
  
  const handleVisibilityChange = () => {
    if (document.visibilityState === 'visible') {
      fetchUsage();
    }
  };
  document.addEventListener('visibilitychange', handleVisibilityChange);
});

onUnmounted(() => {
  if (refreshTimer) clearInterval(refreshTimer);
});

// Computed properties
const HIDDEN_USAGE_MARKERS = ['gateway-injected', 'delivery-mirror'];
const isHiddenUsageSource = (source?: string) => {
  if (!source) return false;
  const normalizedSource = source.trim().toLowerCase();
  return HIDDEN_USAGE_MARKERS.some((marker) => normalizedSource.includes(marker));
};

const formatUsageSource = (source?: string) => {
  if (!source) return undefined;
  if (isHiddenUsageSource(source)) return undefined;
  return source;
};

const shouldHideUsageEntry = (entry: UsageHistoryEntry) => {
  return isHiddenUsageSource(entry.provider) || isHiddenUsageSource(entry.model);
};

const usageHistory = computed(() => fetchState.value.data.filter((entry) => !shouldHideUsageEntry(entry)));
const stableUsageHistory = computed(() => fetchState.value.stableData.filter((entry) => !shouldHideUsageEntry(entry)));

const visibleUsageHistory = computed(() => resolveVisibleUsageHistory(usageHistory.value, stableUsageHistory.value, {
  preferStableOnEmpty: fetchState.value.status === 'loading',
}));

const filteredUsageHistory = computed(() => filterUsageHistoryByWindow(visibleUsageHistory.value, usageWindow.value));
const usageGroups = computed(() => groupUsageHistory(filteredUsageHistory.value, usageGroupBy.value));

const usagePageSize = 5;
const usageTotalPages = computed(() => Math.max(1, Math.ceil(filteredUsageHistory.value.length / usagePageSize)));
const safeUsagePage = computed(() => Math.min(usagePage.value, usageTotalPages.value));

const pagedUsageHistory = computed(() => {
  const start = (safeUsagePage.value - 1) * usagePageSize;
  const end = safeUsagePage.value * usagePageSize;
  return filteredUsageHistory.value.slice(start, end);
});

const formatTokenCount = (value: number) => Intl.NumberFormat().format(value);

const getUsageTotalClass = (entry: UsageHistoryEntry) => {
  if (entry.usageStatus === 'error') return 'font-bold text-[15px] text-red-500';
  if (entry.usageStatus === 'missing') return 'font-bold text-[15px] text-[#99A0AE]';
  return 'font-bold text-[15px] text-[#171717]';
};

const formatUsageTotal = (entry: UsageHistoryEntry) => {
  if (entry.usageStatus === 'error') return '✕';
  if (entry.usageStatus === 'missing') return '—';
  return formatTokenCount(entry.totalTokens);
};

const formatUsageTimestamp = (timestamp: string) => {
  const date = new Date(timestamp);
  if (Number.isNaN(date.getTime())) return timestamp;
  return new Intl.DateTimeFormat(undefined, {
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  }).format(date);
};

watch(usageGroupBy, () => usagePage.value = 1);
watch(usageWindow, () => usagePage.value = 1);
</script>
