package results_download_test

import (
	"bytes"
	"context"
	"encoding/csv"
	"errors"
	"fmt"
	"net/http/httptest"
	"os"
	"testing"

	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
	apirequest "go.avito.ru/av/api-composition-schema/request"
	"go.avito.ru/av/api-composition-schema/response"

	"go.avito.ru/bill/service-fiscal-tool/internal/api/common"
	"go.avito.ru/bill/service-fiscal-tool/internal/api/handler/results_download"
	resultsdownload "go.avito.ru/bill/service-fiscal-tool/internal/generated/api/schema/results_download"
	"go.avito.ru/bill/service-fiscal-tool/internal/repository"
	mockService "go.avito.ru/bill/service-fiscal-tool/mocks/service/file"
)

// tagID 23948 Handle. Файл с результатами. Success path.
func TestHandler_Handle_Success(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	emptyCloser := func() error { return nil }
	urlParams := map[string]string{
		"filename": uuid.New().String(),
	}

	filename, err := uuid.Parse(urlParams["filename"])
	assert.NoError(t, err)

	file, b, err := createCsvFakeFile(t)
	assert.NoError(t, err)

	fileSrv := new(mockService.Service)
	fileSrv.EXPECT().GetResultFile(ctx, filename).Return(file, emptyCloser, nil).Once()
	handler := results_download.New(fileSrv)

	httpReq := httptest.NewRequest("GET", "/api/results/"+urlParams["filename"]+"/download", nil)
	req, err := apirequest.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := resultsdownload.NewParameters(req, urlParams)
	assert.NoError(t, err)

	headers := resultsdownload.OkRespHeaders{}
	headers.SetContentDisposition(fmt.Sprintf("attachment; filename=\"%s\"", urlParams["filename"]+".csv"))

	expectedOut := resultsdownload.NewResponse(response.NewHandlerResponse())
	apiFile := apirequest.NewFile(b)
	expectedOut.OK(apiFile, headers)

	out := resultsdownload.NewResponse(response.NewHandlerResponse())
	err = handler.Handle(ctx, in, out)
	assert.NoError(t, err)
	assert.Equal(t, expectedOut, out)
}

// tagID 23948 Handle. Файл с результатами. Передан невалидный UUID.
func TestHandler_Handle_InvalidUUID(t *testing.T) {
	t.Parallel()

	ctx := context.Background()

	fileSrv := new(mockService.Service)
	handler := results_download.New(fileSrv)

	urlParams := map[string]string{
		"filename": "invalid-uuid-12345",
	}

	httpReq := httptest.NewRequest("GET", "/api/results/"+urlParams["filename"]+"/download", nil)
	req, err := apirequest.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := resultsdownload.NewParameters(req, urlParams)
	assert.NoError(t, err)

	expectedOut := resultsdownload.NewResponse(response.NewHandlerResponse())
	expectedOut.BadRequest(common.BadRequest("invalid filename"))

	out := resultsdownload.NewResponse(response.NewHandlerResponse())
	err = handler.Handle(ctx, in, out)
	assert.NoError(t, err)
	assert.Equal(t, expectedOut, out)
}

// tagID 23948 Handle.  Файл с результатами. Файл не найден.
func TestHandler_Handle_NotFound(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	emptyCloser := func() error { return nil }
	urlParams := map[string]string{
		"filename": uuid.New().String(),
	}

	filename, err := uuid.Parse(urlParams["filename"])
	assert.NoError(t, err)

	fileSrv := new(mockService.Service)
	fileSrv.EXPECT().GetResultFile(ctx, filename).Return(nil, emptyCloser, repository.ErrFileNotFound).Once()
	handler := results_download.New(fileSrv)

	httpReq := httptest.NewRequest("GET", "/api/results/"+urlParams["filename"]+"/download", nil)
	req, err := apirequest.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := resultsdownload.NewParameters(req, urlParams)
	assert.NoError(t, err)

	expectedOut := resultsdownload.NewResponse(response.NewHandlerResponse())
	expectedOut.NotFound(common.NotFound())

	out := resultsdownload.NewResponse(response.NewHandlerResponse())
	err = handler.Handle(ctx, in, out)
	assert.NoError(t, err)
	assert.Equal(t, expectedOut, out)
}

// tagID 23948 Handle. Файл с результатами. Ошибка со стороны S3.
func TestHandler_Handle_S3Failure(t *testing.T) {
	t.Parallel()

	ctx := context.Background()
	emptyCloser := func() error { return nil }
	urlParams := map[string]string{
		"filename": uuid.New().String(),
	}
	expectedErr := errors.New("some error")

	filename, err := uuid.Parse(urlParams["filename"])
	assert.NoError(t, err)

	fileSrv := new(mockService.Service)
	fileSrv.EXPECT().GetResultFile(ctx, filename).Return(nil, emptyCloser, expectedErr).Once()
	handler := results_download.New(fileSrv)

	httpReq := httptest.NewRequest("GET", "/api/results/"+urlParams["filename"]+"/download", nil)
	req, err := apirequest.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := resultsdownload.NewParameters(req, urlParams)
	assert.NoError(t, err)

	out := resultsdownload.NewResponse(response.NewHandlerResponse())
	err = handler.Handle(ctx, in, out)
	assert.ErrorIs(t, err, expectedErr)
}

func createCsvFakeFile(t *testing.T) (*os.File, []byte, error) {
	t.Helper()

	var b bytes.Buffer
	writer := csv.NewWriter(&b)
	err := writer.Write([]string{"First", "Second", "Third"})
	if err != nil {
		return nil, nil, err
	}
	writer.Flush()

	file, err := os.CreateTemp("", "s3file-*.tmp")
	if err != nil {
		return nil, nil, err
	}

	_, err = file.Write(b.Bytes())
	if err != nil {
		return nil, nil, err
	}

	_, err = file.Seek(0, 0)
	if err != nil {
		return nil, nil, err
	}

	return file, b.Bytes(), nil
}


по примеру отсюда сделай разметку тестов тут:

package receipts_import_test

import (
	"bytes"
	"context"
	"crypto/sha256"
	"errors"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"os"
	"strconv"
	"testing"

	"github.com/google/uuid"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"go.avito.ru/av/api-composition-schema/request"
	"go.avito.ru/av/api-composition-schema/response"

	"go.avito.ru/bill/service-fiscal-tool/internal/api/common"
	"go.avito.ru/bill/service-fiscal-tool/internal/api/handler/receipts_import"
	"go.avito.ru/bill/service-fiscal-tool/internal/entity"
	receiptsimport "go.avito.ru/bill/service-fiscal-tool/internal/generated/api/schema/receipts_import"
	"go.avito.ru/bill/service-fiscal-tool/internal/service/task"
	mockfilecorrection "go.avito.ru/bill/service-fiscal-tool/mocks/service/file_correction"
	mocktask "go.avito.ru/bill/service-fiscal-tool/mocks/service/task"
	"go.avito.ru/bill/service-fiscal-tool/pkg/gtc"
)


func TestHandler_Success(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	XBaasUserId := 123
	token := uuid.NewString()
	correctionType := "incorrect"
	// проверяем именно хендлер а не валидатор csv чеков
	fiscalizationCorrectionList := `good csv file`

	httpReq, err := getRequest(
		gtc.String.ValueToPointer(strconv.Itoa(XBaasUserId)),
		&token,
		&correctionType,
		&fiscalizationCorrectionList,
	)
	assert.NoError(t, err)

	fileCorrection := &mockfilecorrection.FileCorrection{}
	fileCorrection.EXPECT().Validate().Return(nil)
	defer fileCorrection.AssertExpectations(t)

	// Не требуется AssertExpectations(t) из-за двойной проверки файла
	fileCorrectionSrv := &mockfilecorrection.Service{}
	fileCorrectionSrv.EXPECT().MakeFromImportFileV2(mock.MatchedBy(func(file *os.File) bool {
		openFile, err := os.Open(file.Name())
		assert.NoError(t, err)
		content, readErr := io.ReadAll(openFile)
		assert.NoError(t, readErr)

		return assert.Equal(t, fiscalizationCorrectionList, string(content))
	})).Return(fileCorrection, nil)

	taskSrv := &mocktask.Service{}
	taskSrv.EXPECT().Create(ctx, mock.MatchedBy(func(atr task.TaskAttr) bool {
		h := sha256.New()
		h.Write([]byte(fiscalizationCorrectionList))

		return assert.Equal(t, uuid.MustParse(token), atr.TaskID) &&
			assert.Equal(t, int64(XBaasUserId), atr.AdminUserId) &&
			assert.Equal(t, entity.CorrectionType(correctionType), atr.CorrectionType) &&
			assert.Equal(t, string(fmt.Sprintf("%x", h.Sum(nil))), atr.FileName) &&
			assert.Equal(t, int64(len(fiscalizationCorrectionList)), atr.FileSize)
	})).Return(nil)
	defer taskSrv.AssertExpectations(t)

	handler := receipts_import.New(taskSrv, fileCorrectionSrv)
	req, err := request.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := receiptsimport.NewFormDataRequest(req, nil)
	assert.NoError(t, err)

	expectedOut := receiptsimport.NewResponse(response.NewHandlerResponse())
	expectedOut.OK()

	out := receiptsimport.NewResponse(response.NewHandlerResponse())
	err = handler.FormDataHandle(ctx, in, out)
	assert.NoError(t, err)
	assert.Equal(t, expectedOut, out)
}

func TestHandler_ParamsNoFile_Invalid(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	tests := []struct {
		name           string
		XBaasUserId    *string
		token          *string
		correctionType *string
		err            string
	}{
		{
			name:           "Empty XBaasUserId",
			XBaasUserId:    nil,
			token:          gtc.String.ValueToPointer(uuid.NewString()),
			correctionType: gtc.String.ValueToPointer(string(entity.CorrectionTypeDouble)),
			err:            "invalid user id",
		},
		{
			name:           "Invalid XBaasUserId",
			XBaasUserId:    gtc.String.ValueToPointer("invalid XBaasUserId"),
			token:          gtc.String.ValueToPointer(uuid.NewString()),
			correctionType: gtc.String.ValueToPointer(string(entity.CorrectionTypeDouble)),
			err:            "invalid user id",
		},
		{
			name:           "Empty token",
			XBaasUserId:    gtc.String.ValueToPointer("123"),
			token:          nil,
			correctionType: gtc.String.ValueToPointer(string(entity.CorrectionTypeDouble)),
			err:            "invalid token",
		},
		{
			name:           "Invalid token",
			XBaasUserId:    gtc.String.ValueToPointer("123"),
			token:          gtc.String.ValueToPointer("invalid token"),
			correctionType: gtc.String.ValueToPointer(string(entity.CorrectionTypeDouble)),
			err:            "invalid token",
		},
		{
			name:           "empty CorrectionType",
			XBaasUserId:    gtc.String.ValueToPointer("123"),
			token:          gtc.String.ValueToPointer(uuid.NewString()),
			correctionType: nil,
			err:            "invalid correctionType",
		},
		{
			name:           "Invalid CorrectionType",
			XBaasUserId:    gtc.String.ValueToPointer("123"),
			token:          gtc.String.ValueToPointer(uuid.NewString()),
			correctionType: gtc.String.ValueToPointer("invalid type"),
			err:            "invalid correctionType",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			t.Parallel()
			httpReq, err := getRequest(
				tt.XBaasUserId,
				tt.token,
				tt.correctionType,
				nil,
			)
			assert.NoError(t, err)

			req, err := request.NewRequest(httpReq)
			assert.NoError(t, err)

			in, err := receiptsimport.NewFormDataRequest(req, nil)
			assert.NoError(t, err)

			expectedOut := receiptsimport.NewResponse(response.NewHandlerResponse())
			expectedOut.BadRequest(common.BadRequest(tt.err))

			handler := receipts_import.New(nil, nil)
			out := receiptsimport.NewResponse(response.NewHandlerResponse())
			err = handler.FormDataHandle(ctx, in, out)
			assert.NoError(t, err)
			assert.Equal(t, expectedOut, out)
		})
	}
}

func TestHandler_File_Empty(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	XBaasUserId := "123"
	token := uuid.NewString()
	correctionType := "double"

	httpReq, err := getRequest(
		gtc.String.ValueToPointer(XBaasUserId),
		&token,
		&correctionType,
		nil,
	)
	assert.NoError(t, err)

	req, err := request.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := receiptsimport.NewFormDataRequest(req, nil)
	assert.NoError(t, err)

	expectedOut := receiptsimport.NewResponse(response.NewHandlerResponse())
	expectedOut.BadRequest(common.BadRequest("invalid fiscalization correction file"))

	handler := receipts_import.New(nil, nil)
	out := receiptsimport.NewResponse(response.NewHandlerResponse())
	err = handler.FormDataHandle(ctx, in, out)
	assert.NoError(t, err)
	assert.Equal(t, expectedOut, out)
}

func TestHandler_File_NotValidate(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	XBaasUserId := "123"
	token := uuid.NewString()
	correctionType := "double"

	fileContent := "not validateble"
	validateErr := errors.New("validation: wrong csv scheme")

	httpReq, err := getRequest(
		gtc.String.ValueToPointer(XBaasUserId),
		&token,
		&correctionType,
		&fileContent,
	)
	assert.NoError(t, err)

	fileCorrection := &mockfilecorrection.FileCorrection{}
	fileCorrection.EXPECT().Validate().Return(validateErr)
	defer fileCorrection.AssertExpectations(t)

	fileCorrectionSrv := &mockfilecorrection.Service{}
	fileCorrectionSrv.EXPECT().MakeFromImportFileV2(mock.MatchedBy(func(file *os.File) bool {
		content, readErr := io.ReadAll(file)
		assert.NoError(t, readErr)

		return assert.Equal(t, fileContent, string(content))
	})).Return(fileCorrection, nil)

	req, err := request.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := receiptsimport.NewFormDataRequest(req, nil)
	assert.NoError(t, err)

	expectedOut := receiptsimport.NewResponse(response.NewHandlerResponse())
	expectedOut.BadRequest(common.BadRequest(validateErr.Error()))

	handler := receipts_import.New(nil, fileCorrectionSrv)
	out := receiptsimport.NewResponse(response.NewHandlerResponse())
	err = handler.FormDataHandle(ctx, in, out)
	assert.NoError(t, err)
	assert.Equal(t, expectedOut, out)
}

func TestHandler_Task_FailCreateTask(t *testing.T) {
	t.Parallel()
	ctx := context.Background()

	XBaasUserId := "123"
	token := uuid.NewString()
	correctionType := "double"
	fileContent := "good file"

	taskCreateErr := errors.New("task create fail")

	httpReq, err := getRequest(
		gtc.String.ValueToPointer(XBaasUserId),
		&token,
		&correctionType,
		&fileContent,
	)
	assert.NoError(t, err)

	fileCorrection := &mockfilecorrection.FileCorrection{}
	fileCorrection.EXPECT().Validate().Return(nil)
	defer fileCorrection.AssertExpectations(t)

	fileCorrectionSrv := &mockfilecorrection.Service{}
	fileCorrectionSrv.EXPECT().MakeFromImportFileV2(mock.Anything).Return(fileCorrection, nil)
	defer fileCorrectionSrv.AssertExpectations(t)

	taskSrv := &mocktask.Service{}
	taskSrv.EXPECT().Create(ctx, mock.Anything).Return(taskCreateErr)
	defer taskSrv.AssertExpectations(t)

	req, err := request.NewRequest(httpReq)
	assert.NoError(t, err)

	in, err := receiptsimport.NewFormDataRequest(req, nil)
	assert.NoError(t, err)

	handler := receipts_import.New(taskSrv, fileCorrectionSrv)
	out := receiptsimport.NewResponse(response.NewHandlerResponse())
	err = handler.FormDataHandle(ctx, in, out)
	assert.Equal(t, taskCreateErr, err)
}

func getRequest(
	XBaasUserId *string,
	token *string,
	correctionType *string,
	fiscalizationCorrectionList *string,
) (*http.Request, error) {
	body := new(bytes.Buffer)
	writer := multipart.NewWriter(body)
	defer func() { writer.Close() }()

	if token != nil {
		tokenWriter, err := writer.CreateFormField("token")
		if err != nil {
			return nil, err
		}

		_, err = tokenWriter.Write([]byte(*token))
		if err != nil {
			return nil, err
		}
	}

	if correctionType != nil {
		correctionTypeWriter, err := writer.CreateFormField("correctionType")
		if err != nil {
			return nil, err
		}

		_, err = correctionTypeWriter.Write([]byte(*correctionType))
		if err != nil {
			return nil, err
		}
	}

	if fiscalizationCorrectionList != nil {
		fiscalizationCorrectionListWriter, err := writer.CreateFormFile("fiscalizationCorrectionList", "receipt.csv")
		if err != nil {
			return nil, err
		}

		_, err = fiscalizationCorrectionListWriter.Write([]byte(*fiscalizationCorrectionList))
		if err != nil {
			return nil, err
		}
	}

	httpReq := httptest.NewRequest("POST", "/api/receipts/import", body)
	httpReq.Header.Set("Content-Type", writer.FormDataContentType())

	if XBaasUserId != nil {
		httpReq.Header.Set("X-Baas-User-Id", *XBaasUserId)
	}

	return httpReq, nil
}


я имею ввиду вот эти теги tagID ..., айди тега оставь тот же