/**
 * 性能监控上报工具
 *
 * - 批量上报：缓冲 5 秒或攒满 20 条再发送，降低请求开销
 * - 自动捕获：页面加载（Navigation Timing）、Supabase Edge Function 调用耗时
 * - 慢请求阈值：>1000ms 标记为慢请求（context.slow=true）
 */

import { supabase } from "@/integrations/supabase/client";

export type MetricType = "page_load" | "api_call" | "custom";

interface PerfRecord {
  metric_type: MetricType;
  metric_name: string;
  duration_ms: number;
  url?: string;
  context?: Record<string, unknown>;
}

const SLOW_THRESHOLD_MS = 1000;
const FLUSH_INTERVAL_MS = 5000;
const FLUSH_BATCH_SIZE = 20;

let buffer: PerfRecord[] = [];
let flushTimer: ReturnType<typeof setTimeout> | null = null;

async function flush(): Promise<void> {
  if (buffer.length === 0) return;
  const batch = buffer.splice(0, buffer.length);
  if (flushTimer) {
    clearTimeout(flushTimer);
    flushTimer = null;
  }
  try {
    const {
      data: { user },
    } = await supabase.auth.getUser();
    const rows = batch.map((r) => ({
      ...r,
      user_id: user?.id ?? null,
      url: r.url ?? (typeof window !== "undefined" ? window.location.href : null),
    }));
    await (supabase.from as any)("perf_logs").insert(rows);
  } catch {
    // 静默失败：性能上报失败不应影响业务
  }
}

function scheduleFlush(): void {
  if (flushTimer) return;
  flushTimer = setTimeout(() => {
    flushTimer = null;
    void flush();
  }, FLUSH_INTERVAL_MS);
}

export function reportMetric(record: PerfRecord): void {
  const slow = record.duration_ms >= SLOW_THRESHOLD_MS;
  buffer.push({
    ...record,
    context: { ...(record.context ?? {}), slow },
  });
  if (buffer.length >= FLUSH_BATCH_SIZE) {
    void flush();
  } else {
    scheduleFlush();
  }
}

/** 测量任意异步函数耗时并自动上报 */
export async function measure<T>(
  name: string,
  fn: () => Promise<T>,
  type: MetricType = "custom",
  extra?: Record<string, unknown>,
): Promise<T> {
  const start = performance.now();
  try {
    const result = await fn();
    reportMetric({
      metric_type: type,
      metric_name: name,
      duration_ms: Math.round(performance.now() - start),
      context: { ...extra, ok: true },
    });
    return result;
  } catch (err) {
    reportMetric({
      metric_type: type,
      metric_name: name,
      duration_ms: Math.round(performance.now() - start),
      context: { ...extra, ok: false, error: String(err) },
    });
    throw err;
  }
}

/** 初始化：捕获页面加载耗时 + 注册 beforeunload flush */
export function initPerfMonitoring(): void {
  if (typeof window === "undefined") return;

  // 页面加载耗时（DOM Interactive 之后再读，确保 timing 已稳定）
  const captureNavTiming = () => {
    try {
      const nav = performance.getEntriesByType("navigation")[0] as
        | PerformanceNavigationTiming
        | undefined;
      if (!nav) return;
      reportMetric({
        metric_type: "page_load",
        metric_name: "navigation",
        duration_ms: Math.round(nav.loadEventEnd - nav.startTime),
        context: {
          dom_content_loaded: Math.round(
            nav.domContentLoadedEventEnd - nav.startTime,
          ),
          ttfb: Math.round(nav.responseStart - nav.requestStart),
          transfer_size: nav.transferSize,
        },
      });
    } catch {
      /* noop */
    }
  };

  if (document.readyState === "complete") {
    captureNavTiming();
  } else {
    window.addEventListener("load", () => setTimeout(captureNavTiming, 0), {
      once: true,
    });
  }

  // 离开页面前确保 flush
  window.addEventListener("beforeunload", () => {
    void flush();
  });

  // visibilitychange 也 flush（移动端切后台）
  document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "hidden") {
      void flush();
    }
  });

  // === Web Vitals: LCP / CLS / INP ===
  // 使用原生 PerformanceObserver，无新依赖；上报为 metric_type=page_load
  try {
    // LCP
    const lcpObs = new PerformanceObserver((list) => {
      const entries = list.getEntries();
      const last = entries[entries.length - 1] as any;
      if (last) {
        reportMetric({
          metric_type: "page_load",
          metric_name: "lcp",
          duration_ms: Math.round(last.renderTime || last.loadTime || last.startTime),
          context: { element: last.element?.tagName },
        });
      }
    });
    lcpObs.observe({ type: "largest-contentful-paint", buffered: true });

    // CLS（累计布局偏移，乘以 1000 以整数毫秒形式存储）
    let clsValue = 0;
    const clsObs = new PerformanceObserver((list) => {
      for (const entry of list.getEntries() as any[]) {
        if (!entry.hadRecentInput) clsValue += entry.value;
      }
    });
    clsObs.observe({ type: "layout-shift", buffered: true });

    const reportCls = () => {
      reportMetric({
        metric_type: "page_load",
        metric_name: "cls",
        duration_ms: Math.round(clsValue * 1000),
        context: { unit: "score*1000" },
      });
    };
    document.addEventListener("visibilitychange", () => {
      if (document.visibilityState === "hidden") reportCls();
    }, { once: true });

    // INP（取最大交互延迟）
    let maxInp = 0;
    const inpObs = new PerformanceObserver((list) => {
      for (const entry of list.getEntries() as any[]) {
        if (entry.duration > maxInp) maxInp = entry.duration;
      }
    });
    try {
      inpObs.observe({ type: "event", buffered: true, durationThreshold: 40 } as any);
    } catch {
      /* 老浏览器不支持 event timing */
    }
    window.addEventListener("beforeunload", () => {
      if (maxInp > 0) {
        reportMetric({
          metric_type: "page_load",
          metric_name: "inp",
          duration_ms: Math.round(maxInp),
        });
      }
    });
  } catch {
    /* PerformanceObserver 不可用，静默 */
  }
}
