package controller

import (
	"context"
	"dashboard/utils"
	"net/http"
	"os/exec"

	"github.com/creack/pty"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"golang.org/x/sync/errgroup"
)

func TerminalHandle() func(c *gin.Context) error {
	upgrader := websocket.Upgrader{
		ReadBufferSize:  1024,
		WriteBufferSize: 1024,
		CheckOrigin: func(r *http.Request) bool {
			return true // 允许跨域
		},
	}
	return func(c *gin.Context) error {
		log, _ := utils.GetLogFromContext(c)

		conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
		if err != nil {
			log.Sugar().Errorf("WebSocket upgrade failed: %v", err)
			return err
		}
		defer conn.Close()

		cmd := exec.Command("bash")
		ptyFile, err := pty.Start(cmd)
		if err != nil {
			log.Sugar().Errorf("Failed to start pty: %v", err)
			return err
		}
		defer ptyFile.Close()

		wg, ctx := errgroup.WithContext(context.Background())

		wg.Go(func() error {
			defer log.Sugar().Errorf("task read over")
			for {
				select {
				case <-ctx.Done():
					log.Sugar().Errorf("task canceld read")
					return ctx.Err()
				default:
				}

				_, msg, err := conn.ReadMessage()
				if err != nil {
					log.Sugar().Errorf("WebSocket read error: %v", err)
					return err
				}
				_, err = ptyFile.Write(msg)
				if err != nil {
					log.Sugar().Errorf("PTY write error: %v", err)
					return err
				}
			}
		})

		wg.Go(func() error {
			defer log.Sugar().Errorf("task write over")
			buf := make([]byte, 1024)
			for {
				select {
				case <-ctx.Done():
					log.Sugar().Errorf("task canceld write")
					return ctx.Err()
				default:
				}

				n, err := ptyFile.Read(buf)
				if err != nil {
					log.Sugar().Errorf("PTY read error: %v", err)
					return err
				}
				err = conn.WriteMessage(websocket.BinaryMessage, buf[:n])
				if err != nil {
					log.Sugar().Errorf("WebSocket write error: %v", err)
					return err
				}
			}
		})

		if err := wg.Wait(); err != nil {
			log.Sugar().Errorf("WebSocket error: %v", err)
		}

		return nil
	}
}
