package cmd

import (
	"fmt"
	"os"
	"strings"
	"time"

	"github.com/innerr/ticat/pkg/core/model"

	"github.com/tidbcloud/controlplane9/internal/cluster"
	"github.com/tidbcloud/controlplane9/internal/config"
	"github.com/tidbcloud/controlplane9/internal/dbaasui"
	cp9errors "github.com/tidbcloud/controlplane9/internal/errors"
	"github.com/tidbcloud/controlplane9/internal/host"
)

type browserAcceptanceResult struct {
	Status       string    `json:"status"`
	Session      string    `json:"session"`
	Origin       string    `json:"origin"`
	Outcome      string    `json:"outcome"`
	Stage        string    `json:"stage"`
	Path         string    `json:"path"`
	CheckedAt    time.Time `json:"checked_at"`
	EvidencePath string    `json:"evidence_path"`
	Message      string    `json:"message"`
}

func (r *browserAcceptanceResult) FormatText() string {
	if r == nil {
		return ""
	}
	return fmt.Sprintf(
		"Browser acceptance: %s\nSession: %s\nOrigin: %s\nStage: %s\nPath: %s\nChecked: %s\nEvidence: %s\n%s\n",
		r.Outcome,
		r.Session,
		r.Origin,
		r.Stage,
		r.Path,
		r.CheckedAt.Format(time.RFC3339),
		r.EvidencePath,
		r.Message,
	)
}

func browserAcceptanceCmd() model.NormalCmd {
	return func(args model.ArgVals, cc *model.Cli, env *model.Env, _ []model.ParsedCmd) error {
		syncVerbose(env)
		cfgPath := args.GetRaw("config")
		version, err := config.DetectAPIVersion(cfgPath)
		if err != nil {
			return err
		}
		if version != config.APIVersionV1Alpha2 {
			return cp9errors.New(
				cp9errors.CategoryConfig,
				"browser acceptance recording requires a cp9.tidbcloud.com/v1alpha2 Session",
			)
		}
		session, err := config.LoadSession(cfgPath)
		if err != nil {
			return err
		}
		session, err = config.ResolveSession(session, cfgPath)
		if err != nil {
			return err
		}
		stateDir := cluster.SessionStateDir(session.Name)
		if _, err := os.Stat(cluster.StatePath(stateDir)); err != nil {
			if os.IsNotExist(err) {
				return cp9errors.Newf(cp9errors.CategoryResource, "Session %q has not been started", session.Name)
			}
			return cp9errors.Newf(cp9errors.CategoryResource, "read Session state: %v", err)
		}
		selected, err := host.Load(stateDir)
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "load selected host: %v", err)
		}
		if selected.Mode != config.HostModeRemoteEC2K3d || selected.Remote == nil {
			return cp9errors.New(
				cp9errors.CategoryConfig,
				"browser acceptance recording requires a remote-ec2-k3d Session with a public UI origin",
			)
		}
		origin := strings.TrimSpace(selected.Remote.PublicHTTPSURL)
		if origin == "" {
			return cp9errors.New(cp9errors.CategoryResource, "selected host has no public UI origin")
		}
		outcome := strings.TrimSpace(args.GetRaw("outcome"))
		stage := strings.TrimSpace(args.GetRaw("stage"))
		if outcome == dbaasui.BrowserOutcomePassed && stage == "" {
			stage = dbaasui.BrowserStageAuthenticatedHistory
		}
		evidence, err := dbaasui.NewBrowserAcceptanceEvidence(
			session.Name,
			origin,
			outcome,
			stage,
			args.GetRaw("path"),
			time.Now(),
		)
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryConfig, "record browser acceptance: %v", err)
		}
		if err := dbaasui.SaveBrowserAcceptance(stateDir, evidence); err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "persist browser acceptance: %v", err)
		}
		return model.Output(cc, env, &browserAcceptanceResult{
			Status:       "recorded",
			Session:      evidence.Session,
			Origin:       evidence.Origin,
			Outcome:      evidence.Outcome,
			Stage:        evidence.Stage,
			Path:         evidence.Path,
			CheckedAt:    evidence.CheckedAt,
			EvidencePath: dbaasui.BrowserAcceptancePath(stateDir),
			Message:      fmt.Sprintf("%s; no credentials, tokens, cookies, headers, or response bodies were stored", evidence.Message()),
		})
	}
}
