/*
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package tasks

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"reflect"
	"strconv"
	"strings"

	"github.com/apache/incubator-devlake/core/dal"
	"github.com/apache/incubator-devlake/core/errors"
	"github.com/apache/incubator-devlake/core/models/domainlayer/didgen"
	"github.com/apache/incubator-devlake/core/models/domainlayer/ticket"
	"github.com/apache/incubator-devlake/core/plugin"
	"github.com/apache/incubator-devlake/helpers/pluginhelper/api"
	"github.com/apache/incubator-devlake/plugins/tapd/models"
)

type Page struct {
	Data Data `json:"data"`
}
type Data struct {
	Count int `json:"count"`
}

var priorityMap = map[string]string{
	"1": "Nice To Have",
	"2": "Low",
	"3": "Middle",
	"4": "High",
}

var accountIdGen *didgen.DomainIdGenerator
var workspaceIdGen *didgen.DomainIdGenerator
var iterIdGen *didgen.DomainIdGenerator

func getAccountIdGen() *didgen.DomainIdGenerator {
	if accountIdGen == nil {
		accountIdGen = didgen.NewDomainIdGenerator(&models.TapdAccount{})
	}
	return accountIdGen
}

func getWorkspaceIdGen() *didgen.DomainIdGenerator {
	if workspaceIdGen == nil {
		workspaceIdGen = didgen.NewDomainIdGenerator(&models.TapdWorkspace{})
	}
	return workspaceIdGen
}

func getIterIdGen() *didgen.DomainIdGenerator {
	if iterIdGen == nil {
		iterIdGen = didgen.NewDomainIdGenerator(&models.TapdIteration{})
	}
	return iterIdGen
}

// res will not be used
func GetTotalPagesFromResponse(r *http.Response, args *api.ApiCollectorArgs) (int, errors.Error) {
	data := args.Ctx.GetData().(*TapdTaskData)
	apiClient, err := NewTapdApiClient(args.Ctx.TaskContext(), data.Connection)
	if err != nil {
		return 0, err
	}
	query := url.Values{}
	query.Set("workspace_id", fmt.Sprintf("%v", data.Options.WorkspaceId))
	res, err := apiClient.Get(fmt.Sprintf("%s/count", r.Request.URL.Path), query, nil)
	if err != nil {
		return 0, err
	}
	var page Page
	err = api.UnmarshalResponse(res, &page)

	count := page.Data.Count
	totalPage := count/args.PageSize + 1

	return totalPage, err
}

// parseIterationChangelog function is used to parse the iteration changelog
func parseIterationChangelog(taskCtx plugin.SubTaskContext, old string, new string) (iterationFromId int64, iterationToId int64, err errors.Error) {
	data := taskCtx.GetData().(*TapdTaskData)
	db := taskCtx.GetDal()

	// Find the iteration with the old name
	iterationFrom := &models.TapdIteration{}
	clauses := []dal.Clause{
		dal.From(&models.TapdIteration{}),
		dal.Where("connection_id = ? and workspace_id = ? and name = ?",
			data.Options.ConnectionId, data.Options.WorkspaceId, old),
	}
	err = db.First(iterationFrom, clauses...)
	if err != nil && !db.IsErrorNotFound(err) {
		return 0, 0, err
	}

	// Find the iteration with the new name
	iterationTo := &models.TapdIteration{}
	clauses = []dal.Clause{
		dal.From(&models.TapdIteration{}),
		dal.Where("connection_id = ? and workspace_id = ? and name = ?",
			data.Options.ConnectionId, data.Options.WorkspaceId, new),
	}
	err = db.First(iterationTo, clauses...)
	if err != nil && !db.IsErrorNotFound(err) {
		return 0, 0, err
	}

	return iterationFrom.Id, iterationTo.Id, nil
}

// GetRawMessageDirectFromResponse extracts the raw message from an HTTP response
func GetRawMessageDirectFromResponse(res *http.Response) ([]json.RawMessage, errors.Error) {
	// Read the response body
	body, err := io.ReadAll(res.Body)
	res.Body.Close()
	if err != nil {
		return nil, errors.Convert(err)
	}
	// Return the response body as a slice of json.RawMessage
	return []json.RawMessage{body}, nil
}

func GetRawMessageArrayFromResponse(res *http.Response) ([]json.RawMessage, errors.Error) {
	var data struct {
		Data []json.RawMessage `json:"data"`
	}
	err := api.UnmarshalResponse(res, &data)
	return data.Data, err
}

type TapdApiParams models.TapdApiParams

// CreateRawDataSubTaskArgs creates a new instance of api.RawDataSubTaskArgs based on the provided
// task context, raw table name, and a flag to determine if the company ID should be used.
// It returns a pointer to the created api.RawDataSubTaskArgs and a pointer to the filtered TapdTaskData.
func CreateRawDataSubTaskArgs(taskCtx plugin.SubTaskContext, rawTable string) (*api.RawDataSubTaskArgs, *TapdTaskData) {
	// Retrieve task data from the provided task context and cast it to TapdTaskData
	data := taskCtx.GetData().(*TapdTaskData)
	// Create a filtered copy of the original data
	filteredData := *data
	filteredData.Options = &TapdOptions{}
	*filteredData.Options = *data.Options
	// Set up TapdApiParams based on the original data
	var params = TapdApiParams{
		ConnectionId: data.Options.ConnectionId,
		WorkspaceId:  data.Options.WorkspaceId,
	}
	// Create the RawDataSubTaskArgs with the task context, params, and raw table name
	rawDataSubTaskArgs := &api.RawDataSubTaskArgs{
		Ctx:    taskCtx,
		Params: params,
		Table:  rawTable,
	}
	// Return the created RawDataSubTaskArgs and the filtered TapdTaskData
	return rawDataSubTaskArgs, &filteredData
}

// getTapdTypeMappings retrieves story types from _tool_tapd_workitem_types and maps them to
// typeMapping. It takes TapdTaskData, a Dal interface, and a system string as arguments.
// It returns a map of type ID to type name and an error, if any.
func getTapdTypeMappings(data *TapdTaskData, db dal.Dal, system string) (map[uint64]string, errors.Error) {
	typeIdMapping := make(map[uint64]string)
	issueTypes := make([]models.TapdWorkitemType, 0)
	// Create clauses for querying the database
	clauses := []dal.Clause{
		dal.From(&models.TapdWorkitemType{}),
		dal.Where("connection_id = ? and workspace_id = ? and entity_type = ?",
			data.Options.ConnectionId, data.Options.WorkspaceId, system),
	}
	// Query the database for issue types
	err := db.All(&issueTypes, clauses...)
	if err != nil {
		return nil, err
	}
	// Map the retrieved issue types
	for _, issueType := range issueTypes {
		typeIdMapping[issueType.Id] = issueType.Name
	}
	return typeIdMapping, nil
}

// getStdTypeMappings creates a map of user type to standard type based on the provided TapdTaskData.
// It returns the created map.
func getStdTypeMappings(data *TapdTaskData) map[string]string {
	stdTypeMappings := make(map[string]string)
	if data.Options.ScopeConfig == nil {
		return stdTypeMappings
	}
	mapping := data.Options.ScopeConfig.TypeMappings
	// Map user types to standard types
	for userType, stdType := range mapping {
		stdTypeMappings[userType] = strings.ToUpper(stdType)
	}
	return stdTypeMappings
}

// getStatusMapping creates a map of original status values to standard status values
// based on the provided TapdTaskData. It returns the created map.
func getStatusMapping(data *TapdTaskData) map[string]string {
	stdStatusMappings := make(map[string]string)
	if data.Options.ScopeConfig == nil {
		return stdStatusMappings
	}
	mapping := data.Options.ScopeConfig.StatusMappings
	// Map original status values to standard status values
	for userStatus, stdStatus := range mapping {
		stdStatusMappings[userStatus] = strings.ToUpper(stdStatus)
	}
	return stdStatusMappings
}

// getDefaultStdStatusMapping retrieves default standard status mappings for the given TapdTaskData and status list.
// It takes TapdTaskData, a Dal interface, and a statusList of type S (models.TapdStatus).
// It returns a map of English to Chinese status names, a function to get standard status from status key, and an error, if any.
func getDefaultStdStatusMapping[S models.TapdStatus](data *TapdTaskData, db dal.Dal, statusList []S) (map[string]string, func(statusKey string) string, errors.Error) {
	// Create clauses for querying the database
	clauses := []dal.Clause{
		dal.Where("connection_id = ? and workspace_id = ?", data.Options.ConnectionId, data.Options.WorkspaceId),
	}
	// Query the database for status list
	err := db.All(&statusList, clauses...)
	if err != nil {
		return nil, nil, err
	}

	// Create status language and last step maps
	statusLanguageMap := make(map[string]string, len(statusList))
	statusLastStepMap := make(map[string]bool, len(statusList))

	// Populate status maps
	for _, v := range statusList {
		statusLanguageMap[v.GetEnglish()] = v.GetChinese()
		statusLastStepMap[v.GetChinese()] = v.GetIsLastStep()
	}

	// Define function to get standard status from status key
	getStdStatus := func(statusKey string) string {
		if statusLastStepMap[statusKey] {
			return ticket.DONE
		} else if statusKey == "草稿" {
			return ticket.TODO
		} else {
			return ticket.IN_PROGRESS
		}
	}
	return statusLanguageMap, getStdStatus, nil
}

// unicodeToZh converts a string containing Unicode escape sequences to a Chinese string.
// It returns the converted string and an error if the conversion fails.
func unicodeToZh(s string) (string, error) {
	str, err := strconv.Unquote(strings.Replace(strconv.Quote(s), `\\u`, `\u`, -1))
	if err != nil {
		return "", err
	}
	return str, nil
}

// convertUnicode converts the ValueAfterParsed and ValueBeforeParsed fields of a struct to Chinese text.
// It takes a pointer to a struct and returns an error if the conversion fails.
func convertUnicode(p interface{}) errors.Error {
	var err errors.Error
	pType := reflect.TypeOf(p)
	if pType.Kind() != reflect.Ptr {
		panic("expected a pointer to a struct")
	}
	pValue := reflect.ValueOf(p).Elem()
	if pValue.Kind() != reflect.Struct {
		panic("expected a pointer to a struct")
	}
	after, err := errors.Convert01(unicodeToZh(pValue.FieldByName("ValueAfterParsed").String()))
	if err != nil {
		return err
	}
	before, err := errors.Convert01(unicodeToZh(pValue.FieldByName("ValueBeforeParsed").String()))
	if err != nil {
		return err
	}
	if after == "--" {
		after = ""
	}
	if before == "--" {
		before = ""
	}
	// Set ValueAfterParsed and ValueBeforeParsed fields
	valueAfterField := pValue.FieldByName("ValueAfterParsed")
	valueAfterField.SetString(after)
	valueBeforeField := pValue.FieldByName("ValueBeforeParsed")
	valueBeforeField.SetString(before)
	return nil
}

// replaceSemicolonWithComma replaces all semicolons with commas in the given string
// and trims any trailing commas. It returns the modified string.
func replaceSemicolonWithComma(str string) string {
	res := strings.ReplaceAll(str, ";", ",")
	return strings.TrimRight(res, ",")
}

// generateDomainAccountIdForUsers generates domain account IDs for a list of users.
// The input 'param' is a string with format "user1,user2,user3".
// The function takes a string containing a list of users separated by commas and a connectionId.
// It returns a string containing the generated domain account IDs for each user, separated by commas.
func generateDomainAccountIdForUsers(param string, connectionId uint64) string {
	if param == "" {
		return ""
	}
	param = replaceSemicolonWithComma(param)
	users := strings.Split(param, ",")
	var res []string
	for _, user := range users {
		res = append(res, getAccountIdGen().Generate(connectionId, user))
	}
	return strings.Join(res, ",")
}

// extractStatus extracts the status from the given blob and returns a map of status names to status values.
func extractStatus(blob []byte) (map[string]string, errors.Error) {
	var statusRes struct {
		Data interface{} `json:"data"`
	}
	err := errors.Convert(json.Unmarshal(blob, &statusRes))
	if err != nil {
		return nil, err
	}
	data, ok := statusRes.Data.(map[string]interface{})
	if !ok {
		return nil, nil
	}
	results := make(map[string]string)
	for k, v := range data {
		if value, ok := v.(string); ok {
			results[k] = value
		}
	}
	return results, nil
}

// getRepoNamespaceFromUrlPath
// returns the namespace of a repository from the given URL path,
// which is the url path without the last segment, and without leading and trailing slashes.
func getRepoNamespaceFromUrlPath(path string) string {
	// Remove leading and trailing slashes
	path = strings.Trim(path, "/")
	// Remove last segment
	path = path[:strings.LastIndex(path, "/")]
	return path
}

// getRepoNameFromUrlPath
// returns the last segment of url path as repo name, without .git suffix.
func getRepoNameFromUrlPath(path string) string {
	// Remove leading and trailing slashes
	path = strings.Trim(path, "/")
	// Remove .git suffix
	path = strings.TrimSuffix(path, ".git")
	// Get last segment
	return path[strings.LastIndex(path, "/")+1:]
}
