package integration_test

import (
	"net/http"
	"testing"

	v1 "github.com/AlchemyTelcoSolutions/callisto-so-bff/api/v1"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/cmd/app/config"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/integration_tests/app"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/integration_tests/expect"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/integration_tests/fakes"
	suiteclient "github.com/AlchemyTelcoSolutions/callisto-so-bff/integration_tests/suite-client"
	testclient "github.com/AlchemyTelcoSolutions/callisto-so-bff/integration_tests/test-client"
	"github.com/AlchemyTelcoSolutions/callisto-so-bff/internal/domain/model"
	"github.com/AlchemyTelcoSolutions/xutils-go/xlogger"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/suite"
)

type saleOrderExportASNSuite struct {
	suite.Suite
	Log             xlogger.Logger
	Server          *testclient.ServerClientBuilder
	ClientGenerator *suiteclient.ClientGenerator
}

func (s *saleOrderExportASNSuite) TestSaleOrderExportASNToFile() {
	t := s.T()

	tests := []struct {
		name     string
		cfg      config.Config
		orderRef v1.OrderReference
		params   v1.ExportASNToFileParams
		assert   func(t *testing.T, resp *model.ProxyResponse)
	}{
		{
			name: "EXPORT_ASN_FILE_HAPPY_PATH",
			cfg: config.Config{
				CallistoSO: config.CallistoSOConfig{
					Enabled: true,
				},
				CallistoAPI: config.CallistoAPIConfig{
					Host:      "http://127.0.0.1:4000",
					SaleOrder: config.SaleOrderAPI{},
					Bids:      config.BidsAPI{},
					Auth: config.AuthAPI{
						Me: "/v1/auth/me/proxy/success",
					},
				},
			},
			orderRef: fakes.OrderRefWithShipmentAndASNData,
			params:   v1.ExportASNToFileParams{Format: v1.Csv},
			assert: func(t *testing.T, resp *model.ProxyResponse) {
				assert.Equal(t, http.StatusOK, resp.StatusCode)
				assert.Equal(t, "attachment; filename=ASN-9999.csv", resp.Header["Content-Disposition"])
				assert.Equal(t, "text/csv", resp.Header["Content-Type"])
				assert.Equal(t, fakes.ExportASNSuccessResponse, resp.BodyBytes)
			},
		},
		{
			name: "EXPORT_ASN_FILE_INVALID_FORMAT",
			cfg: config.Config{
				CallistoSO: config.CallistoSOConfig{
					Enabled: true,
				},
				CallistoAPI: config.CallistoAPIConfig{
					Host:      "http://127.0.0.1:4000",
					SaleOrder: config.SaleOrderAPI{},
					Bids:      config.BidsAPI{},
					Auth: config.AuthAPI{
						Me: "/v1/auth/me/proxy/success",
					},
				},
			},
			orderRef: fakes.OrderRefWithShipmentAndASNData,
			params:   v1.ExportASNToFileParams{Format: "pdf"},
			assert: func(t *testing.T, resp *model.ProxyResponse) {
				assert.Equal(t, http.StatusUnsupportedMediaType, resp.StatusCode)
				assert.Equal(t, "application/json", resp.Header["Content-Type"])
				expect.ValidExportASNDataErrorResponse(t, resp.BodyBytes, fakes.ExportASNUnsupportedFileFormatMessage)
			},
		},
		{
			name: "EXPORT_ASN_FILE_FAILED_GET_SHIPMENTS",
			cfg: config.Config{
				CallistoSO: config.CallistoSOConfig{
					Enabled: true,
				},
				CallistoAPI: config.CallistoAPIConfig{
					Host:      "http://127.0.0.1:4000",
					SaleOrder: config.SaleOrderAPI{},
					Bids:      config.BidsAPI{},
					Auth: config.AuthAPI{
						Me: "/v1/auth/me/proxy/success",
					},
				},
			},
			orderRef: fakes.OrderRefWithShipmentError,
			params:   v1.ExportASNToFileParams{Format: v1.Csv},
			assert: func(t *testing.T, resp *model.ProxyResponse) {
				assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
				assert.Equal(t, "application/json", resp.Header["Content-Type"])
				expect.ValidExportASNDataErrorResponse(t, resp.BodyBytes, fakes.ExportASNFailedGetShipmentMessage)
			},
		},
		{
			name: "EXPORT_ASN_FILE_NO_SHIPMENTS",
			cfg: config.Config{
				CallistoSO: config.CallistoSOConfig{
					Enabled: true,
				},
				CallistoAPI: config.CallistoAPIConfig{
					Host:      "http://127.0.0.1:4000",
					SaleOrder: config.SaleOrderAPI{},
					Bids:      config.BidsAPI{},
					Auth: config.AuthAPI{
						Me: "/v1/auth/me/proxy/success",
					},
				},
			},
			orderRef: fakes.OrderRefWithNoShipment,
			params:   v1.ExportASNToFileParams{Format: v1.Csv},
			assert: func(t *testing.T, resp *model.ProxyResponse) {
				assert.Equal(t, http.StatusNotFound, resp.StatusCode)
				assert.Equal(t, "application/json", resp.Header["Content-Type"])
				expect.ValidExportASNDataErrorResponse(t, resp.BodyBytes, fakes.ExportASNNoShipmentMessage)
			},
		},
		{
			name: "EXPORT_ASN_FILE_FAILED_GET_ASN",
			cfg: config.Config{
				CallistoSO: config.CallistoSOConfig{
					Enabled: true,
				},
				CallistoAPI: config.CallistoAPIConfig{
					Host:      "http://127.0.0.1:4000",
					SaleOrder: config.SaleOrderAPI{},
					Bids:      config.BidsAPI{},
					Auth: config.AuthAPI{
						Me: "/v1/auth/me/proxy/success",
					},
				},
			},
			orderRef: fakes.OrderRefWithASNError,
			params:   v1.ExportASNToFileParams{Format: v1.Csv},
			assert: func(t *testing.T, resp *model.ProxyResponse) {
				assert.Equal(t, http.StatusInternalServerError, resp.StatusCode)
				assert.Equal(t, "application/json", resp.Header["Content-Type"])
				expect.ValidExportASNDataErrorResponse(t, resp.BodyBytes, fakes.ExportASNFailedGetASNMessage)
			},
		},
		{
			name: "EXPORT_ASN_FILE_NO_ASN",
			cfg: config.Config{
				CallistoSO: config.CallistoSOConfig{
					Enabled: true,
				},
				CallistoAPI: config.CallistoAPIConfig{
					Host:      "http://127.0.0.1:4000",
					SaleOrder: config.SaleOrderAPI{},
					Bids:      config.BidsAPI{},
					Auth: config.AuthAPI{
						Me: "/v1/auth/me/proxy/success",
					},
				},
			},
			orderRef: fakes.OrderRefWithNoASN,
			params:   v1.ExportASNToFileParams{Format: v1.Csv},
			assert: func(t *testing.T, resp *model.ProxyResponse) {
				assert.Equal(t, http.StatusNotFound, resp.StatusCode)
				assert.Equal(t, "application/json", resp.Header["Content-Type"])
				expect.ValidExportASNDataErrorResponse(t, resp.BodyBytes, fakes.ExportASNNoASNMessage)
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			testApp := app.NewTestApp(&test.cfg, s.Log)

			// build new server with custom config
			server := s.Server.SetTestApp(testApp).SetAppConfig(&test.cfg).Build()

			// create suite client by custom server
			cli := suiteclient.NewClientGenerator(server).NewClient(t)

			resp := cli.ExportASNToFile(test.orderRef, test.params)
			test.assert(t, resp)
		})
	}
}
