package dm_svc

import (
	"errors"
	"fmt"
	"strings"

	"github.com/pingcap/tiflow/dm/pkg/checker"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/serverless-service/internal/domain/entity"
)

const (
	dmPrecheckExecutionFailedPrefix = "precheck execution failed:"
	dmPrecheckMessagePrefix         = "Message:"
	dmPrecheckWorkaroundPrefix      = "Workaround:"

	// dmPrecheckSkippedDueToInitFailureReasonFmt is used for items after the first execution
	// failure: they share the same root cause but were not run individually.
	dmPrecheckSkippedDueToInitFailureReasonFmt = "This check was not executed because precheck initialization failed: %s"
)

func errorMessage(err error) string {
	if err == nil {
		return ""
	}
	var be bizerr.BizError
	if errors.As(err, &be) {
		return be.ErrMsg()
	}
	return err.Error()
}

// extractDMPrecheckUserError extracts user-facing reason and workaround from mgmt errors
// prefixed with "precheck execution failed:". Other errors (network, timeout, etc.) return ok=false
// so the worker can treat them as internal failures.
func extractDMPrecheckUserError(err error) (reason, workaround string, ok bool) {
	msg := errorMessage(err)
	if !strings.Contains(msg, dmPrecheckExecutionFailedPrefix) {
		return "", "", false
	}

	messageIdx := strings.Index(msg, dmPrecheckMessagePrefix)
	workaroundIdx := strings.Index(msg, dmPrecheckWorkaroundPrefix)

	if messageIdx >= 0 {
		messageStart := messageIdx + len(dmPrecheckMessagePrefix)
		messageEnd := len(msg)
		if workaroundIdx > messageIdx {
			messageEnd = workaroundIdx
		}
		reason = strings.TrimSpace(msg[messageStart:messageEnd])
		reason = strings.TrimSuffix(reason, ",")
	}

	if workaroundIdx >= 0 {
		workaround = strings.TrimSpace(msg[workaroundIdx+len(dmPrecheckWorkaroundPrefix):])
	}

	if reason == "" {
		// No "Message:" field; use text after the prefix. Truncate at "Workaround:" so it is
		// not duplicated into reason when only a workaround is present.
		prefixIdx := strings.Index(msg, dmPrecheckExecutionFailedPrefix)
		reasonEnd := len(msg)
		if workaroundIdx > prefixIdx {
			reasonEnd = workaroundIdx
		}
		reason = strings.TrimSpace(msg[prefixIdx+len(dmPrecheckExecutionFailedPrefix) : reasonEnd])
		reason = strings.TrimSuffix(reason, ",")
	}

	if reason == "" {
		return "", "", false
	}
	return reason, workaround, true
}

func buildSkippedDueToInitFailureReason(initReason string) string {
	return fmt.Sprintf(dmPrecheckSkippedDueToInitFailureReasonFmt, initReason)
}

// buildDMPrecheckFailureResults builds checker-shaped results so GetPrecheck can reuse the
// same formatting path as a normal per-item check failure (reason/solution from ShortErr/Instruction).
func buildDMPrecheckFailureResults(desc, reason, workaround string) entity.Results {
	return entity.Results{
		Results: []*checker.Result{
			{
				Desc:  desc,
				State: checker.StateFailure,
				Errors: []*checker.Error{
					{
						Severity: checker.StateFailure,
						ShortErr: reason,
					},
				},
				Instruction: workaround,
			},
		},
	}
}
