// Package worker_sampledataapp add by blacknc <blacknc@163.com> at 2023/09/25 17:08:31
package worker_sampledataapp

import (
	"context"
	"dataservices/commons/constants"
	dto "dataservices/internal/dto/dataapi"
	"dataservices/internal/entity"
	"dataservices/internal/repository"
	service "dataservices/internal/service/central"
	"encoding/json"
	"fmt"
	"net/http"
)

var defaultSampleDataappEndpoints = []entity.Endpoint{}

type CreateEndpointState struct{}

func (s *CreateEndpointState) String() string {
	return entity.SampleDataTaskStateCreateEndpoint
}

func (s *CreateEndpointState) Exec(c *SampleDataappContext) {
	var err error
	defer func() {
		if err != nil {
			c.Trans(&FailState{s, err})
		} else {
			c.Trans(&DeployEndpointState{})
		}
	}()

	err = repository.Transaction(c.ctx, func(ctx context.Context) error {
		for _, endpoint := range defaultSampleDataappEndpoints {
			endpoint.DataappId = c.dataapp.ID
			endpoint.ClusterId = c.clusterID
			endpoint.CreatedBy = c.dataapp.CreatedBy
			endpoint.UpdatedBy = c.dataapp.CreatedBy
			if _, err := repository.CreateEndpoint(ctx, &endpoint, nil); err != nil {
				return err
			}
			if err := service.PublishEndpointActionEvent(ctx, endpoint.ID, c.dataapp.CreatedBy, dto.EndpointActionSave); err != nil {
				return err
			}
		}
		return nil
	})
}

func init() {
	defaultSetting := entity.EndpointSettings{
		RowsLimit: constants.EndpointDefaultRowlimit,
		TimeOut:   constants.EndpointDefaultTimeoutMs,
	}
	settingBytes, _ := json.Marshal(defaultSetting)

	sqlPrefix := `/* Getting Started:
Enter "USE {database};" before entering your SQL statements.
Type "--your question" + Enter to try out AI-generated SQL queries
Declare a parameter like "Where id = ${arg}".
*/
`

	// TopNByYear Endpoint
	topNArgs := []entity.EndpointArgs{
		{
			Name:        "year",
			Type:        entity.FieldTypeString,
			Description: "Year",
			Default:     "2022",
		},
		{
			Name:        "N",
			Type:        entity.FieldTypeNumber,
			Description: "Number of top companies to retrieve.",
			Default:     "10",
		},
	}
	topNArgsBytes, _ := json.Marshal(topNArgs)
	topNEndpoint := entity.Endpoint{
		Name:        "topNRankedCompaniesByYear",
		Endpoint:    "/api/companies/topNByYear",
		Method:      http.MethodGet,
		Type:        entity.EndpointTypeChat2Sql,
		Settings:    string(settingBytes),
		Args:        string(topNArgsBytes),
		Batch:       false,
		Tag:         "Default",
		Description: "Get data for the top N Fortune 500 companies for a specific year.",
		RWMode:      constants.SqlModeReadOnly,
		SqlTemplate: fmt.Sprintf(`%sSELECT
	%s,
	%s
FROM
	fortune500.fortune500_2018_2022
WHERE
	%s = ${year}
ORDER BY
	%[3]s ASC
LIMIT ${N};`, sqlPrefix, "`company_name`", "`rank`", "`year`"),
	}
	defaultSampleDataappEndpoints = append(defaultSampleDataappEndpoints, topNEndpoint)

	// PerfHistory Endpoint
	perfArgs := []entity.EndpointArgs{
		{
			Name:        "companyName",
			Type:        entity.FieldTypeString,
			Description: "The company name",
			Default:     "Walmart",
		},
	}
	perfArgsBytes, _ := json.Marshal(perfArgs)
	perfEndpoint := entity.Endpoint{
		Name:        "perfHistoryByCompany",
		Endpoint:    "/api/companies/perfHistory",
		Method:      http.MethodGet,
		Type:        entity.EndpointTypeChat2Sql,
		Settings:    string(settingBytes),
		Args:        string(perfArgsBytes),
		Batch:       false,
		Tag:         "Default",
		Description: "Get historical data for a specific company.",
		RWMode:      constants.SqlModeReadOnly,
		SqlTemplate: fmt.Sprintf(`%sSELECT
	*
FROM
	fortune500.fortune500_2018_2022
WHERE
	%s = ${companyName}
ORDER BY
	%s;`, sqlPrefix, "`company_name`", "`year`"),
	}
	defaultSampleDataappEndpoints = append(defaultSampleDataappEndpoints, perfEndpoint)

	// DistributionByYear Endpoint
	distributionArgs := []entity.EndpointArgs{
		{
			Name:        "year",
			Type:        entity.FieldTypeString,
			Description: "Year",
			Default:     "2022",
		},
	}
	distributionBytes, _ := json.Marshal(distributionArgs)
	distributionEndpoint := entity.Endpoint{
		Name:        "dataAvailablePerCountryByYear",
		Endpoint:    "/api/countries/distributionByYear",
		Method:      http.MethodGet,
		Type:        entity.EndpointTypeChat2Sql,
		Settings:    string(settingBytes),
		Args:        string(distributionBytes),
		Batch:       false,
		Tag:         "Default",
		Description: "This interface is designed to retrieve the distribution of the top 500 companies by country for a specific year.",
		RWMode:      constants.SqlModeReadOnly,
		SqlTemplate: fmt.Sprintf(`%sSELECT
	%s,
	COUNT(*) AS %s
FROM
	fortune500.fortune500_2018_2022
WHERE
	%s = ${year}
GROUP BY
	%[2]s
ORDER BY
	%[3]s DESC;`, sqlPrefix, "`country`", "`count`", "`year`"),
	}
	defaultSampleDataappEndpoints = append(defaultSampleDataappEndpoints, distributionEndpoint)

	// Top500CountByCountry Endpoint
	top500CountArgs := []entity.EndpointArgs{
		{
			Name:        "country",
			Type:        entity.FieldTypeString,
			Description: "The name of the country to be queried.",
			Default:     "USA",
		},
	}
	top500CountBytes, _ := json.Marshal(top500CountArgs)
	top500CountEndpoint := entity.Endpoint{
		Name:        "fortune500CountByCountry",
		Endpoint:    "/api/countries/top500CountByCountry",
		Method:      http.MethodGet,
		Type:        entity.EndpointTypeChat2Sql,
		Settings:    string(settingBytes),
		Args:        string(top500CountBytes),
		Batch:       false,
		Tag:         "Default",
		Description: "Retrieve the change in the number of the top 500 companies for a specific country over recent years.",
		RWMode:      constants.SqlModeReadOnly,
		SqlTemplate: fmt.Sprintf(`%sSELECT
	%s,
	COUNT(*) AS count
FROM
	fortune500.fortune500_2018_2022
WHERE
	%s = ${country}
GROUP BY
	%[2]s
ORDER BY
	%[2]s;`, sqlPrefix, "`year`", "`country`"),
	}
	defaultSampleDataappEndpoints = append(defaultSampleDataappEndpoints, top500CountEndpoint)
}
