/*
 * Copyright 2026 Oleg Borodin <onborodin@gmail.com>
 *
 * This work is published and licensed under a Creative Commons
 * Attribution-NonCommercial-NoDerivatives 4.0 International License.
 *
 * Distribution of this work is permitted, but commercial use and
 * modifications are strictly prohibited.
 */
package test

import (
	"github.com/stretchr/testify/require"

	"bytes"
	"encoding/hex"
	"fmt"
	"io"
	"math/rand"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"strconv"
	"testing"

	"mstore/app/router"
	"mstore/app/server"
)

func xxxTestFileOperations(t *testing.T) {
	var err error
	fmt.Printf("=== MakeServer ===\n")
	srv, err := server.NewServer()
	require.NoError(t, err)

	var srvport int64 = 10240 + rand.Int63n(1024)
	srvdir := t.TempDir()

	filename := `bare.bin`

	{
		err = srv.Configure()
		require.NoError(t, err)

		err = srv.Configure()
		require.NoError(t, err)

		useTmpdir := false

		if useTmpdir {
			srv.SetDatadir(srvdir)
			srv.SetLogdir(srvdir)
			srv.SetRundir(srvdir)
		}
		srv.SetPort(srvport)

		err = srv.Build()
		require.NoError(t, err)
	}
	{
		fmt.Printf("=== ServiceHello ===\n")
		reqPath := "/service/hello"
		routePath := "/service/hello"

		rout := router.NewRouter()
		hand := srv.Handler()
		rout.Get(routePath, hand.SendHello)

		request, err := http.NewRequest("GET", reqPath, nil)
		require.NoError(t, err)

		recorder := httptest.NewRecorder()
		rout.ServeHTTP(recorder, request)
		require.Equal(t, http.StatusOK, recorder.Code)

		fmt.Printf("Response code: %d\n", recorder.Code)

		bodyReader := recorder.Body
		bodyBytes, err := io.ReadAll(bodyReader)

		fmt.Printf("Response body: %s\n", string(bodyBytes))
	}
	{
		fmt.Printf("=== PutFile ===\n")
		reqPath := `/v3/api/file/` + filename
		routePath := `/v3/api/file/{filepath}`

		rout := router.NewRouter()
		hand := srv.Handler()
		require.NotNil(t, hand)

		rout.Put(routePath, hand.PutFile)

		datasize := 64
		filedata := make([]byte, datasize)
		_, err = rand.Read(filedata)
		require.NoError(t, err)

		filedata = []byte(hex.EncodeToString(filedata))
		datasize *= 2

		source := bytes.NewReader(filedata)

		request, err := http.NewRequest("PUT", reqPath, source)
		require.NoError(t, err)

		request.ContentLength = int64(datasize)
		request.Header.Set("Content-Type", "application/octet-stream")
		request.Header.Set("Content-Size", strconv.FormatInt(int64(datasize), 10))

		recorder := httptest.NewRecorder()
		rout.ServeHTTP(recorder, request)
		require.Equal(t, http.StatusOK, recorder.Code)

		fmt.Printf("Response code: %d\n", recorder.Code)

		bodyReader := recorder.Body
		bodyBytes, err := io.ReadAll(bodyReader)

		fmt.Printf("Response body: %s\n", string(bodyBytes))
	}
	{
		fmt.Printf("=== FileInfo ===\n")

		reqPath := filepath.Join(`/v3/api/file`, filename)
		routePath := `/v3/api/file/{filepath}`

		rout := router.NewRouter()
		hand := srv.Handler()
		require.NotNil(t, hand)

		rout.Head(routePath, hand.FileInfo)

		request, err := http.NewRequest("HEAD", reqPath, nil)
		require.NoError(t, err)

		recorder := httptest.NewRecorder()
		rout.ServeHTTP(recorder, request)
		require.Equal(t, http.StatusOK, recorder.Code)

		fmt.Printf("Response code: %d\n", recorder.Code)

		bodyReader := recorder.Body
		bodyBytes, err := io.ReadAll(bodyReader)

		fmt.Printf("Response body: %s\n", string(bodyBytes))
	}
	{
		fmt.Printf("=== GetFile ===\n")
		reqPath := filepath.Join(`/v3/api/file`, filename)
		routePath := `/v3/api/file/{filepath}`

		rout := router.NewRouter()
		hand := srv.Handler()
		require.NotNil(t, hand)

		rout.Get(routePath, hand.GetFile)

		request, err := http.NewRequest("GET", reqPath, nil)
		require.NoError(t, err)

		recorder := httptest.NewRecorder()
		rout.ServeHTTP(recorder, request)
		require.Equal(t, http.StatusOK, recorder.Code)

		fmt.Printf("Response code: %d\n", recorder.Code)

		bodyReader := recorder.Body
		bodyBytes, err := io.ReadAll(bodyReader)

		fmt.Printf("Response body: %s\n", string(bodyBytes))
	}
	return
	{
		fmt.Printf("=== DeleteFile ===\n")
		reqPath := filepath.Join(`/v3/api/file`, filename)
		routePath := `/v3/api/file/{filepath}`

		rout := router.NewRouter()
		hand := srv.Handler()
		require.NotNil(t, hand)

		rout.Delete(routePath, hand.DeleteFile)

		request, err := http.NewRequest("DELETE", reqPath, nil)
		require.NoError(t, err)

		recorder := httptest.NewRecorder()
		rout.ServeHTTP(recorder, request)
		require.Equal(t, http.StatusOK, recorder.Code)

		fmt.Printf("Response code: %d\n", recorder.Code)

		bodyReader := recorder.Body
		bodyBytes, err := io.ReadAll(bodyReader)

		fmt.Printf("Response body: %s\n", string(bodyBytes))
	}

	{
		fmt.Printf("=== FileNotExists ===\n")

		reqPath := filepath.Join(`/v3/api/file`, filename)
		routePath := `/v3/api/file/{filepath}`

		rout := router.NewRouter()
		hand := srv.Handler()
		require.NotNil(t, hand)

		rout.Head(routePath, hand.FileInfo)

		request, err := http.NewRequest("HEAD", reqPath, nil)
		require.NoError(t, err)

		recorder := httptest.NewRecorder()
		rout.ServeHTTP(recorder, request)
		require.Equal(t, http.StatusNotFound, recorder.Code)

		fmt.Printf("Response code: %d\n", recorder.Code)

		bodyReader := recorder.Body
		bodyBytes, err := io.ReadAll(bodyReader)

		fmt.Printf("Response body: %s\n", string(bodyBytes))
	}
}
