// Package server 提供 pprof 性能分析的底层实现。
//
// 该文件封装 runtime/pprof 的调用，为 fasthttp 提供流式输出支持。
// 包含以下核心功能：
//   - CPU profile 的启动和停止
//   - 内存分配 profile 的写入
//   - Goroutine stack traces 的写入
//   - 阻塞和锁竞争 profile 的写入
//
// 主要用途：
//
//	作为 pprof.go 的底层实现层，处理与 runtime/pprof 的直接交互。
//
// 注意事项：
//   - CPU profile 使用互斥锁保护，确保并发安全
//   - 所有写入操作均使用 io.Writer 接口，支持流式输出
//
// 作者：xfy
package server

import (
	"bufio"
	"io"
	"runtime"
	"runtime/pprof"
	"sync"
)

var (
	// cpuProfileMu 保护 cpuProfileActive 状态的互斥锁。
	//
	// 用于确保 CPU profiling 启动和停止操作的线程安全性，
	// 防止并发调用 startCPUProfile/stopCPUProfile 导致的状态不一致。
	cpuProfileMu sync.Mutex

	// cpuProfileActive 标记当前 CPU profile 是否处于采集状态。
	//
	// 值为 true 表示正在采集，false 表示未采集。
	// 该变量由 cpuProfileMu 保护，不应直接访问。
	cpuProfileActive bool
)

// startCPUProfile 启动 CPU profile 采集。
//
// 参数：
//   - w: 输出 writer
//
// 返回值：
//   - error: 启动失败时的错误
func startCPUProfile(w io.Writer) error {
	cpuProfileMu.Lock()
	defer cpuProfileMu.Unlock()

	if cpuProfileActive {
		return nil // 已在采集，忽略
	}

	if err := pprof.StartCPUProfile(w); err != nil {
		return err
	}

	cpuProfileActive = true
	return nil
}

// stopCPUProfile 停止 CPU profile 采集。
//
// 终止正在进行的 CPU profile 采集，并将缓冲数据刷新到输出。
// 若当前无活跃采集，则忽略该调用。
//
// 注意事项：
//   - 该函数由 cpuProfileMu 保护，调用前无需额外加锁
func stopCPUProfile() {
	cpuProfileMu.Lock()
	defer cpuProfileMu.Unlock()

	if cpuProfileActive {
		pprof.StopCPUProfile()
		cpuProfileActive = false
	}
}

// writeHeapProfile 写入内存分配 profile。
//
// 执行 GC 后采集内存分配数据并写入输出流。
// GC 可确保获取更准确的内存使用数据。
//
// 参数：
//   - w: 输出 writer，用于写入 profile 数据
func writeHeapProfile(w io.Writer) {
	runtime.GC() // 先执行 GC，获取更准确的数据
	_ = pprof.WriteHeapProfile(w)
}

// writeGoroutineProfile 写入 Goroutine stack traces。
//
// 采集当前所有 Goroutine 的栈追踪信息并写入输出流。
//
// 参数：
//   - w: 输出 writer，用于写入 profile 数据
func writeGoroutineProfile(w io.Writer) {
	p := pprof.Lookup("goroutine")
	if p != nil {
		_ = p.WriteTo(w, 0)
	}
}

// writeBlockProfile 写入阻塞 profile。
//
// 采集阻塞操作的 profile 数据并写入输出流。
//
// 参数：
//   - w: 输出 writer，用于写入 profile 数据
func writeBlockProfile(w io.Writer) {
	p := pprof.Lookup("block")
	if p != nil {
		_ = p.WriteTo(w, 0)
	}
}

// writeMutexProfile 写入锁竞争 profile。
//
// 采集互斥锁竞争的 profile 数据并写入输出流。
//
// 参数：
//   - w: 输出 writer，用于写入 profile 数据
func writeMutexProfile(w io.Writer) {
	p := pprof.Lookup("mutex")
	if p != nil {
		_ = p.WriteTo(w, 0)
	}
}

// writeAllocsProfile 写入分配 profile。
//
// 与 heap profile 使用同一份数据，但默认以分配视角展示（Samples=alloc_*）。
// 等价于 net/http/pprof 的 /debug/pprof/allocs。
//
// 参数：
//   - w: 输出 writer，用于写入 profile 数据
func writeAllocsProfile(w io.Writer) {
	p := pprof.Lookup("allocs")
	if p != nil {
		_ = p.WriteTo(w, 0)
		return
	}
	// 如果 allocs profile 未注册，回退到 heap profile
	runtime.GC()
	_ = pprof.WriteHeapProfile(w)
}

// bufioWriterAdapter 将 bufio.Writer 包装为 io.Writer，自动 Flush。
//
// 该结构体实现 io.Writer 接口，在每次写入后自动调用 Flush，
// 确保数据立即发送到客户端，适用于流式响应场景。
type bufioWriterAdapter struct {
	// w 被包装的 bufio.Writer
	w *bufio.Writer
}

// Write 实现 io.Writer 接口，写入数据并自动 Flush。
//
// 参数：
//   - p: 待写入的字节切片
//
// 返回值：
//   - n: 实际写入的字节数
//   - err: 写入过程中遇到的错误
func (a *bufioWriterAdapter) Write(p []byte) (n int, err error) {
	n, err = a.w.Write(p)
	if err == nil {
		_ = a.w.Flush()
	}
	return n, err
}

// wrapBufioWriter 将 bufio.Writer 包装为 io.Writer。
//
// 创建一个 bufioWriterAdapter 实例，使 bufio.Writer 能够
// 在每次写入后自动 Flush，满足流式输出的需求。
//
// 参数：
//   - w: 待包装的 bufio.Writer
//
// 返回值：
//   - io.Writer: 包装后的 io.Writer 接口实例
func wrapBufioWriter(w *bufio.Writer) io.Writer {
	return &bufioWriterAdapter{w: w}
}
