package features

import (
	"fmt"
	"time"

	"github.com/onsi/ginkgo/v2"

	"github.com/fatedier/frp/test/e2e/framework"
)

var _ = ginkgo.Describe("[Feature: Chaos]", func() {
	f := framework.NewDefaultFramework()

	ginkgo.It("reconnect after frps restart", func() {
		serverPort := f.AllocPort()
		serverConfigPath := f.GenerateConfigFile(fmt.Sprintf(`
		bindAddr = "0.0.0.0"
		bindPort = %d
		`, serverPort))

		remotePort := f.AllocPort()
		clientConfigPath := f.GenerateConfigFile(fmt.Sprintf(`
		serverPort = %d
		log.level = "trace"

		[[proxies]]
		name = "tcp"
		type = "tcp"
		localPort = %d
		remotePort = %d
		`, serverPort, f.PortByName(framework.TCPEchoServerPort), remotePort))

		// 1. start frps and frpc, expect request success
		ps, _, err := f.RunFrps("-c", serverConfigPath)
		framework.ExpectNoError(err)

		pc, _, err := f.RunFrpc("-c", clientConfigPath)
		framework.ExpectNoError(err)
		framework.NewRequestExpect(f).Port(remotePort).Ensure()

		// 2. stop frps, expect request failed
		_ = ps.Stop()
		framework.NewRequestExpect(f).Port(remotePort).ExpectError(true).Ensure()

		// 3. restart frps, expect request success
		successCount := pc.CountOutput("[tcp] start proxy success")
		_, _, err = f.RunFrps("-c", serverConfigPath)
		framework.ExpectNoError(err)
		framework.ExpectNoError(pc.WaitForOutput("[tcp] start proxy success", successCount+1, 5*time.Second))
		framework.NewRequestExpect(f).Port(remotePort).Ensure()

		// 4. stop frpc, expect request failed
		_ = pc.Stop()
		framework.ExpectNoError(framework.WaitForTCPUnreachable(fmt.Sprintf("127.0.0.1:%d", remotePort), 100*time.Millisecond, 5*time.Second))
		framework.NewRequestExpect(f).Port(remotePort).ExpectError(true).Ensure()

		// 5. restart frpc, expect request success
		newPc, _, err := f.RunFrpc("-c", clientConfigPath)
		framework.ExpectNoError(err)
		framework.ExpectNoError(newPc.WaitForOutput("[tcp] start proxy success", 1, 5*time.Second))
		framework.NewRequestExpect(f).Port(remotePort).Ensure()
	})
})
