package tests

import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"net/http"
	"testing"
	"time"

	"github.com/google/uuid"
	"github.com/pingcap/dbaas/billing2/constant"
	"github.com/pingcap/dbaas/billing2/db"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/model/marketing"
	"github.com/pingcap/dbaas/billing2/model/marketing/unit_filter"
	"github.com/pingcap/dbaas/billing2/model/payment/paymentsub"
	"github.com/pingcap/dbaas/billing2/utils/timeutils"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/dbaas/billing2/api"
	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/model/billing"
	"github.com/pingcap/dbaas/billing2/model/payment"
	"github.com/pingcap/dbaas/billing2/utils/ginutils"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/pingcap/dbaas/billing2/utils/tests/datainit"
	"github.com/shopspring/decimal"
	"github.com/stretchr/testify/suite"
)

type CostExplorerTestSuite struct {
	tests.BillingTestSuite
	router *gin.Engine
}

func (suite *CostExplorerTestSuite) SetupTest() {
	suite.BillingTestSuite.SetupTest()
	suite.router = gin.New()
	suite.router.Use(ginutils.ErrorMiddleWare)
	api.InitializeCostExplorerRouter(ginutils.MyRoute{Route: suite.router})
}

func TestCostExplorerSuite(t *testing.T) {
	suite.Run(t, new(CostExplorerTestSuite))
}

func (suite *CostExplorerTestSuite) TestCostExplorerQuery() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)
	_, err := datainit.CreateInvoice(uint(1))
	assert.NoError(err)
	query := &forms.CostExplorerQuery{
		StartDate: datainit.BillingDate,
		EndDate:   datainit.BillingDate.Add(time.Hour),
	}
	w := tests.PerformRequest(suite.router, "POST", "/tenants/1/costexplorer", query)
	assert.Equal(http.StatusOK, w.Code)
	res := &forms.CostExplorerResult{}
	assert.NoError(json.Unmarshal(w.Body.Bytes(), res))
	assert.Equal(res.BindedInvoiceCosts.CostPrice, decimal.NewFromInt(1))

}

func (suite *CostExplorerTestSuite) TestInternalCostExplorerQuery() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)
	_, err := datainit.CreateInvoice(uint(1))
	assert.NoError(err)
	query := &forms.CostExplorerQuery{
		StartDate: datainit.BillingDate,
		EndDate:   datainit.BillingDate.Add(time.Hour),
	}
	w := tests.PerformRequest(suite.router, "POST", "/tenants/1/internal/costexplorer", query)
	assert.Equal(http.StatusOK, w.Code)
	res := &forms.CostExplorerResult{}
	assert.NoError(json.Unmarshal(w.Body.Bytes(), res))
	assert.Equal(res.BindedInvoiceCosts.CostPrice, decimal.NewFromInt(1))

}

func (suite *CostExplorerTestSuite) TestInternalCostExplorerQueryV2() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)
	_, err := datainit.CreateInvoice(uint(1))
	assert.NoError(err)
	query := &forms.CostExplorerQueryV2{
		StartDate: datainit.BillingDate,
		EndDate:   datainit.BillingDate.Add(time.Hour),
	}
	w := tests.PerformRequest(suite.router, "POST", "/tenants/1/internal/costexplorer/v2", query)
	assert.Equal(http.StatusOK, w.Code)
	res := &forms.CompleteCostExplorerResult{}
	assert.NoError(json.Unmarshal(w.Body.Bytes(), res))
	assert.Equal(res.ExternalCosts.BindedInvoiceCosts.CostPrice, decimal.NewFromInt(1))
}

func (suite *CostExplorerTestSuite) TestCostExplorerMontlyQuery() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)
	_, err := datainit.CreateInvoice(uint(1))
	assert.NoError(err)
	path := fmt.Sprintf("/tenants/1/costexplorer/monthly_cost/year/%d/month/%d", datainit.BillingDate.Year(), datainit.BillingDate.Month())
	w := tests.PerformRequest(suite.router, "GET", path, nil)
	assert.Equal(http.StatusOK, w.Code, w.Body.String())
	res := &forms.MonthlycostExplorerResult{}
	assert.NoError(json.Unmarshal(w.Body.Bytes(), res))
	assert.Equal(res.BindedInvoiceCosts.CostPrice, decimal.NewFromInt(1))
	assert.Equal(res.InvoiceGenerated, true)

	path = fmt.Sprintf("/tenants/1/costexplorer/monthly_cost/year/%d/month/%d", datainit.BillingDate.Year(), datainit.BillingDate.Month()+1)
	w = tests.PerformRequest(suite.router, "GET", path, nil)
	assert.Equal(http.StatusOK, w.Code, w.Body.String())
	res = &forms.MonthlycostExplorerResult{}
	assert.NoError(json.Unmarshal(w.Body.Bytes(), res))
	assert.Equal(res.InvoiceGenerated, true)

}

func (suite *CostExplorerTestSuite) TestCostExplorerMontlyQueryNotGenearted() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)
	err := datainit.CreateMeasures(uint(1))
	assert.NoError(err)
	path := fmt.Sprintf("/tenants/1/costexplorer/monthly_cost/year/%d/month/%d", datainit.BillingDate.Year(), datainit.BillingDate.Month()+1)
	w := tests.PerformRequest(suite.router, "GET", path, nil)
	assert.Equal(http.StatusOK, w.Code, w.Body.String())
	res := &forms.MonthlycostExplorerResult{}
	assert.NoError(json.Unmarshal(w.Body.Bytes(), res))
	assert.Equal(res.UnbindedInvoiceCosts.CostPrice, decimal.Zero)
	assert.Equal(res.InvoiceGenerated, false)
}

func (suite *CostExplorerTestSuite) TestCostExplorerMontlyQueryExport() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)

	fmt.Print(config.Get().GetBool(config.EnableCache))
	_, err := (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   "test_unitA",
		Category:  "category_A",
		Price:     decimal.RequireFromString("0.001"),
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)

	_, err = (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   "test_unitB",
		Category:  "category_B",
		Price:     decimal.RequireFromString("0.001"),
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)

	var billingDate = datainit.BillingDate

	measureModel := &billing.MeasureModel{}
	const tenantID uint = 1
	assert.NoError(datainit.CreatePaymentMock(tenantID))
	billingConfigID := uint(1)
	_, err = (&billing.BindedPackageModel{}).BindPackageExtra(tenantID, &forms.BindedPackageInfoInput{
		PackageID:             datainit.NoUsePackageId,
		DiscountEnabled:       true,
		Internal:              false,
		InvoicePayable:        true,
		BindedBillingConfigID: &billingConfigID,
	})
	unitCosts := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          "test_unitA",
		Cost:          1004,
		Labels:        map[string]string{},
	}

	unitCosts.Labels["project"] = "A"
	_, err = measureModel.CostUnits(tenantID, &unitCosts)
	assert.NoError(err)
	unitCosts.Labels["project"] = "B"
	_, err = measureModel.CostUnits(tenantID, &unitCosts)
	assert.NoError(err)
	unitCosts.Labels["project"] = "C"
	_, err = measureModel.CostUnits(tenantID, &unitCosts)
	assert.NoError(err)

	unitCosts.Unit = "test_unitB"

	unitCosts.Labels["project"] = "A"
	_, err = measureModel.CostUnits(tenantID, &unitCosts)
	assert.NoError(err)
	unitCosts.Labels["project"] = "B"
	_, err = measureModel.CostUnits(tenantID, &unitCosts)
	assert.NoError(err)
	unitCosts.Labels["project"] = "C"
	_, err = measureModel.CostUnits(tenantID, &unitCosts)
	assert.NoError(err)

	path := fmt.Sprintf("/tenants/1/costexplorer/monthly_cost/year/%d/month/%d/export", datainit.BillingDate.Year(), datainit.BillingDate.Month())
	w := tests.PerformRequest(suite.router, "POST", path, nil)
	assert.Equal(http.StatusOK, w.Code, w.Body.String())
	records, err := csv.NewReader(w.Body).ReadAll()
	assert.NoError(err)
	lastLine := records[len(records)-1]
	lastValue := lastLine[len(lastLine)-1]
	assert.Equal(lastValue, "6")
	assert.Equal(records[0][0], "Project")
	assert.Equal(records[0][1], "category_A")
	assert.Equal(records[0][2], "category_B")
	assert.Equal(records[0][3], "Total")
	assert.Equal(records[1][0], "A")
	assert.Equal(records[2][0], "B")
	assert.Equal(records[3][0], "C")
	assert.Equal(records[4][0], "Total")

	invoiceModel := &payment.InvoiceModel{}

	_, err = invoiceModel.CreateMonthlyInvoice(uint(1), 1, datainit.BillingDate)
	assert.NoError(err)
	w = tests.PerformRequest(suite.router, "POST", path, nil)
	records, err = csv.NewReader(w.Body).ReadAll()
	assert.NoError(err)
	lastLine = records[len(records)-1]
	lastValue = lastLine[len(lastLine)-1]
	assert.Equal(lastValue, "6")
}

func (suite *CostExplorerTestSuite) TestMonthlyBillsExportIncludesUsageAndUnit() {
	assert := suite.Assert()
	datainit.CreateBillingConfig(1, entity.BillingConfigType_DirectCustomer)
	datainit.CreateCategoryLabels()

	_, err := (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:     "serverless-ru:aws:us-west-2",
		Category:    "Serverless Request Unit Cost",
		Provider:    "AWS",
		Region:      "us-west-2",
		MeasureUnit: "UnitTableShouldBeIgnored",
		Price:       decimal.RequireFromString("0.001"),
		PriceType:   entity.PriceType_Normal,
	})
	assert.NoError(err)

	billingDate := datainit.BillingDate
	measureModel := &billing.MeasureModel{}
	const tenantID uint = 1
	assert.NoError(datainit.CreatePaymentMock(tenantID))
	billingConfigID := uint(1)
	_, err = (&billing.BindedPackageModel{}).BindPackageExtra(tenantID, &forms.BindedPackageInfoInput{
		PackageID:             datainit.NoUsePackageId,
		DiscountEnabled:       true,
		Internal:              false,
		InvoicePayable:        true,
		BindedBillingConfigID: &billingConfigID,
	})
	assert.NoError(err)

	_, err = measureModel.CostUnits(tenantID, &forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          "serverless-ru:aws:us-west-2",
		Cost:          3000,
		Labels: map[string]string{
			"project":   "Project A",
			"projectID": "10",
			"cluster":   "Cluster A",
			"clusterID": "100",
		},
	})
	assert.NoError(err)

	// The bills export endpoint now includes Usage/Unit appended at the end.
	exportPath := fmt.Sprintf("/tenants/1/costexplorer/monthly_bills/year/%d/month/%d/export", billingDate.Year(), billingDate.Month())
	w := tests.PerformRequest(suite.router, "POST", exportPath, nil)
	assert.Equal(http.StatusOK, w.Code, w.Body.String())

	reader := csv.NewReader(w.Body)
	reader.FieldsPerRecord = -1
	records, err := reader.ReadAll()
	assert.NoError(err)
	expectedHeader := []string{"Billed Date", "Service", "Cloud Provider", "Region", "Project Name", "Project ID", "Cluster ID", "Cluster Name", "Running Total", "Discounts", "Credits", "Total Cost", "Usage", "Unit"}
	var headerRow, dataRow []string
	for _, record := range records {
		if len(record) == len(expectedHeader) && record[0] == "Billed Date" {
			headerRow = record
		}
		if len(record) == len(expectedHeader) && record[5] == "10" && record[6] == "100" {
			dataRow = record
		}
	}
	assert.Equal(expectedHeader, headerRow)
	// The original bills CSV columns must keep their positions so existing
	// position-based report consumers are not broken; Usage/Unit are appended.
	assert.Equal([]string{"Billed Date", "Service", "Cloud Provider", "Region", "Project Name", "Project ID", "Cluster ID", "Cluster Name", "Running Total", "Discounts", "Credits", "Total Cost"}, headerRow[:12])
	assert.Equal("AWS", dataRow[2])
	assert.Equal("us-west-2", dataRow[3])
	assert.Equal("3000", dataRow[12])
	assert.Equal("RU", dataRow[13])
}

func (suite *CostExplorerTestSuite) TestBillsCostExplorerIgnoreBeta() {
	assert := suite.Assert()

	var billingDate = time.Date(2021, 11, 1, 0, 0, 0, 0, time.UTC)
	measureModel := &billing.MeasureModel{}
	const tenantID uint = 1
	datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)

	err := datainit.CreatePaymentMock(tenantID)
	assert.NoError(err)

	u1, err := (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   "test_unitA",
		Category:  "category_A",
		Price:     decimal.NewFromInt(1),
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)

	u2, err := (&billing.UnitModel{}).CreateUnit(&forms.UnitInfo{
		UnitKey:   "test_unitB",
		Category:  "category_B",
		Price:     decimal.NewFromInt(1),
		PriceType: entity.PriceType_Normal,
	})
	assert.NoError(err)
	generalUnitFilter, err := (&unit_filter.Model{}).CreateUnitFilter(&forms.UnitFilter{
		UnitFilterSlim: forms.UnitFilterSlim{Name: "General", Description: "General"},
		General:        true,
	})
	billingConfigID := uint(1)
	creditsPackage := &forms.CreditsPackage{
		StartDate:             timeutils.GetMonthDate(billingDate),
		ExpiredDate:           billingDate.AddDate(0, 1, 0),
		TotalCredits:          decimal.NewFromInt(10),
		Usage:                 entity.CreditsPackageType_General,
		UnitFilters:           []*forms.UnitFilterSlim{{TypeID: generalUnitFilter.FilterID}},
		DiscountEnabled:       true,
		BindedBillingConfigID: &billingConfigID,
	}
	creditsPackage, err = (&marketing.CreditsPackageModel{}).CreateCreditsPackage(tenantID, creditsPackage)

	unitCosts1 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          u1.UnitKey,
		Cost:          5,
	}
	unitCosts2 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          u2.UnitKey,
		Cost:          5,
	}
	unitCosts3 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          u1.UnitKey,
		Cost:          5,
		Labels:        map[string]string{constant.BetaLabelKey: constant.BetaLabelValueTrue},
	}
	unitCosts4 := forms.UnitCosts{
		CostTimeStamp: billingDate.Unix(),
		Unit:          u2.UnitKey,
		Cost:          5,
		Labels:        map[string]string{constant.BetaLabelKey: constant.BetaLabelValueTrue, constant.BetaCategoryLabelKey: "2222"},
	}
	_, err = measureModel.CostUnits(tenantID, &unitCosts1)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts2)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts3)
	assert.NoError(err)
	_, err = measureModel.CostUnits(tenantID, &unitCosts4)
	assert.NoError(err)
	res := forms.CostExplorerResult{}
	path := fmt.Sprintf("/tenants/%d/internal/costexplorer", tenantID)
	w := tests.PerformRequest(suite.router, "POST", path, &forms.CostExplorerInternalQuery{
		StartDate:  billingDate,
		EndDate:    billingDate.Add(time.Hour),
		Units:      []string{u1.UnitKey, u2.UnitKey},
		IgnoreBeta: true,
	})
	assert.Equal(http.StatusOK, w.Code)
	assert.NoError(err)
	err = json.Unmarshal(w.Body.Bytes(), &res)
	assert.NoError(err)
	assert.Equal(decimal.NewFromInt(10), res.CreditsCosts.CostPrice)
	assert.Equal(decimal.NewFromInt(0), res.UnbindedInvoiceCosts.RawPrice)
	assert.Equal(decimal.NewFromInt(0), res.UnbindedInvoiceCosts.CostPrice)
	assert.Equal(decimal.NewFromInt(0), res.BindedInvoiceCosts.CostPrice)
	assert.Equal(decimal.NewFromInt(0), res.InvoiceCostsCosts.CostPrice)
	assert.Equal(decimal.NewFromInt(10), res.TotalCosts.CostPrice)
	assert.Equal(decimal.NewFromInt(10), res.TotalCosts.RawPrice)
	w = tests.PerformRequest(suite.router, "POST", path, &forms.CostExplorerInternalQuery{
		StartDate: billingDate,
		EndDate:   billingDate.Add(time.Hour),
		Units:     []string{u1.UnitKey, u2.UnitKey},
	})
	assert.NoError(err)
	assert.Equal(http.StatusOK, w.Code)
	assert.NoError(err)
	err = json.Unmarshal(w.Body.Bytes(), &res)
	assert.NoError(err)
	assert.Equal(decimal.NewFromInt(10), res.UnbindedInvoiceCosts.RawPrice)
	assert.Equal(decimal.NewFromInt(10), res.TotalCosts.CostPrice)
	assert.Equal(decimal.NewFromInt(20), res.TotalCosts.RawPrice)
}

func (suite *CostExplorerTestSuite) TestAliCloudMarketplaceMonthlyBillsExport() {
	assert := suite.Assert()
	var err error
	datainit.CreateCategoryLabels()
	datainit.CreateDefaultUnits()
	tests.MockPaymentHandler()
	tests.MockCentralHandler()
	err = datainit.CreateCompany()
	assert.NoError(err)

	normalID := uint(3)
	billingConfigs := make([]*forms.BillingConfig, 3)
	payments := make([]*forms.PaymentMethod, len(billingConfigs))
	for i := 0; i != len(billingConfigs); i++ {
		var err error
		billingConfigs[i], err = datainit.CreateBillingConfig(uint(i+1), entity.BillingConfigType_DirectCustomer)
		assert.NoError(err)
		payments[i], err = (&paymentsub.PaymentModel{}).CreatePaymentMethodAndActive(
			billingConfigs[i].TenantID,
			&forms.PaymentMethodCreateQuery{
				PaymentType:           "mock",
				BindedBillingConfigID: &billingConfigs[i].BillingConfigID,
			},
		)
		for j := 0; j != 30; j++ {
			cost := entity.UserUnitCost{
				CostID:                uuid.NewString(),
				Cost:                  10,
				Unit:                  datainit.SupportCommitmentUnit,
				CostTimeStamp:         datainit.BillingDate.AddDate(0, 0, j).Unix(),
				RawPrice:              decimal.NewFromInt(10),
				CostPrice:             decimal.NewFromInt(10),
				Type:                  entity.UserUnitCostType_Merged,
				Status:                entity.UserUnitCostStatus_DONE,
				InvoiceID:             entity.InvoiceUnbindID,
				Labels:                map[string]string{constant.ClusterLabelKey: fmt.Sprint(i*2 + 1)},
				Internal:              false,
				ConsumedSource:        entity.ConsumedSource_Invoice,
				BindedBillingConfigID: billingConfigs[i].BillingConfigID,
				TenantID:              billingConfigs[i].TenantID,
			}
			err = cost.Create(db.GetDB())
			assert.NoError(err)
		}
		inv, err := invoiceModel.CreateCostQuotaInvoice(billingConfigs[i].TenantID, billingConfigs[i].BillingConfigID, datainit.BillingDate)
		assert.NoError(err)
		if normalID != billingConfigs[i].TenantID {
			paymentType := entity.PaymentType_AliCloud
			err = entity.NewPaymentMethodQuerySet(db.GetDB()).IDEq(payments[i].PaymentMethodID).GetUpdater().SetPaymentType(paymentType).Update()
			assert.NoError(err)
		}
		err = entity.NewInvoiceQuerySet(db.GetDB()).IDEq(inv.InvoiceID).GetUpdater().SetStatus(entity.InvoiceStatus_SENT).SetPaymentType(&payments[i].PaymentType).SetPaymentCode(&payments[i].PaymentCode).Update()
		assert.NoError(err)
	}

	w := tests.PerformRequest(suite.router, "POST", "/providers/alicloud/costexplorer/monthly_bills/year/2021/month/11/export", nil)
	assert.Equal(http.StatusOK, w.Code)
	assert.Equal(`Billing Period,11/01/21-11/30/21
Customer ID,Billed Date,Service,Region,Cluster ID,Total Cost
mock_1,2021-11-01,Support Plan,-,1,10
mock_1,2021-11-02,Support Plan,-,1,10
mock_1,2021-11-03,Support Plan,-,1,10
mock_1,2021-11-04,Support Plan,-,1,10
mock_1,2021-11-05,Support Plan,-,1,10
mock_1,2021-11-06,Support Plan,-,1,10
mock_1,2021-11-07,Support Plan,-,1,10
mock_1,2021-11-08,Support Plan,-,1,10
mock_1,2021-11-09,Support Plan,-,1,10
mock_1,2021-11-10,Support Plan,-,1,10
mock_1,2021-11-11,Support Plan,-,1,10
mock_1,2021-11-12,Support Plan,-,1,10
mock_1,2021-11-13,Support Plan,-,1,10
mock_1,2021-11-14,Support Plan,-,1,10
mock_1,2021-11-15,Support Plan,-,1,10
mock_1,2021-11-16,Support Plan,-,1,10
mock_1,2021-11-17,Support Plan,-,1,10
mock_1,2021-11-18,Support Plan,-,1,10
mock_1,2021-11-19,Support Plan,-,1,10
mock_1,2021-11-20,Support Plan,-,1,10
mock_1,2021-11-21,Support Plan,-,1,10
mock_1,2021-11-22,Support Plan,-,1,10
mock_1,2021-11-23,Support Plan,-,1,10
mock_1,2021-11-24,Support Plan,-,1,10
mock_1,2021-11-25,Support Plan,-,1,10
mock_1,2021-11-26,Support Plan,-,1,10
mock_1,2021-11-27,Support Plan,-,1,10
mock_1,2021-11-28,Support Plan,-,1,10
mock_1,2021-11-29,Support Plan,-,1,10
mock_1,2021-11-30,Support Plan,-,1,10
mock_2,2021-11-01,Support Plan,-,3,10
mock_2,2021-11-02,Support Plan,-,3,10
mock_2,2021-11-03,Support Plan,-,3,10
mock_2,2021-11-04,Support Plan,-,3,10
mock_2,2021-11-05,Support Plan,-,3,10
mock_2,2021-11-06,Support Plan,-,3,10
mock_2,2021-11-07,Support Plan,-,3,10
mock_2,2021-11-08,Support Plan,-,3,10
mock_2,2021-11-09,Support Plan,-,3,10
mock_2,2021-11-10,Support Plan,-,3,10
mock_2,2021-11-11,Support Plan,-,3,10
mock_2,2021-11-12,Support Plan,-,3,10
mock_2,2021-11-13,Support Plan,-,3,10
mock_2,2021-11-14,Support Plan,-,3,10
mock_2,2021-11-15,Support Plan,-,3,10
mock_2,2021-11-16,Support Plan,-,3,10
mock_2,2021-11-17,Support Plan,-,3,10
mock_2,2021-11-18,Support Plan,-,3,10
mock_2,2021-11-19,Support Plan,-,3,10
mock_2,2021-11-20,Support Plan,-,3,10
mock_2,2021-11-21,Support Plan,-,3,10
mock_2,2021-11-22,Support Plan,-,3,10
mock_2,2021-11-23,Support Plan,-,3,10
mock_2,2021-11-24,Support Plan,-,3,10
mock_2,2021-11-25,Support Plan,-,3,10
mock_2,2021-11-26,Support Plan,-,3,10
mock_2,2021-11-27,Support Plan,-,3,10
mock_2,2021-11-28,Support Plan,-,3,10
mock_2,2021-11-29,Support Plan,-,3,10
mock_2,2021-11-30,Support Plan,-,3,10
`, w.Body.String())
}
