package cmd

import (
	"context"
	"strings"
	"time"

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

	cp9errors "github.com/tidbcloud/controlplane9/internal/errors"
)

// inventoryVolumesCmd implements the read-only `cp9 inventory volumes` command.
//
// inventory is the READ-ONLY, see-and-explain complement of `cp9 purge`: it
// reasons about standalone orphaned resources purge intentionally will not touch
// (no trusted parent to prove scope), classifying them and recommending a safe
// action. It never mutates tags or deletes (PRD #596). See docs/adr/0007 for
// the purge/inventory boundary.
//
// It reports account-wide CP9 EC2 volumes with attribution, confidence,
// active/stale state, missing cp9 labels, and a recommended cleanup action.
// Account, role, and profile are operator/env configuration shared with cp9 purge.
func inventoryVolumesCmd() model.NormalCmd {
	return func(args model.ArgVals, cc *model.Cli, env *model.Env, _ []model.ParsedCmd) error {
		syncVerbose(env)

		opCfg := loadPurgeOperatorConfig(args.GetRaw("region"))
		ctx := context.Background()

		// Same fail-closed guard as purge: confirm we run as the cleanup role in
		// the expected account before reading the account inventory.
		if err := verifyPurgeIdentity(ctx, opCfg); err != nil {
			return err
		}

		awsCfg, err := cmdLoadAWSConfig(ctx, opCfg.Profile, opCfg.Region)
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory: load aws config: %v", err)
		}
		inv, err := cmdInventoryVolumes(ctx, cmdNewInventoryEC2Client(&awsCfg), opCfg.Region, opCfg.AccountID, time.Now())
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory volumes: %v", err)
		}
		inv.SummaryOnly = inventorySummaryOnly(args)
		return model.Output(cc, env, &inv)
	}
}

// inventoryInstancesCmd implements the read-only `cp9 inventory instances`
// command: the same read-only attribution as inventory volumes, applied to EC2
// instances. It never mutates tags or deletes. See docs/adr/0007.
func inventoryInstancesCmd() model.NormalCmd {
	return func(args model.ArgVals, cc *model.Cli, env *model.Env, _ []model.ParsedCmd) error {
		syncVerbose(env)

		opCfg := loadPurgeOperatorConfig(args.GetRaw("region"))
		ctx := context.Background()

		if err := verifyPurgeIdentity(ctx, opCfg); err != nil {
			return err
		}

		awsCfg, err := cmdLoadAWSConfig(ctx, opCfg.Profile, opCfg.Region)
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory instances: load aws config: %v", err)
		}
		inv, err := cmdInventoryInstances(ctx, cmdNewInventoryEC2Client(&awsCfg), opCfg.Region, opCfg.AccountID, time.Now())
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory instances: %v", err)
		}
		inv.SummaryOnly = inventorySummaryOnly(args)
		return model.Output(cc, env, &inv)
	}
}

// inventorySecurityGroupsCmd implements the read-only `cp9 inventory
// security-groups` command: the same read-only attribution applied to EC2
// security groups (the default VPC SG is always protected). It never mutates
// tags or deletes. See docs/adr/0007.
func inventorySecurityGroupsCmd() model.NormalCmd {
	return func(args model.ArgVals, cc *model.Cli, env *model.Env, _ []model.ParsedCmd) error {
		syncVerbose(env)

		opCfg := loadPurgeOperatorConfig(args.GetRaw("region"))
		ctx := context.Background()

		if err := verifyPurgeIdentity(ctx, opCfg); err != nil {
			return err
		}

		awsCfg, err := cmdLoadAWSConfig(ctx, opCfg.Profile, opCfg.Region)
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory security-groups: load aws config: %v", err)
		}
		inv, err := cmdInventorySecurityGroups(ctx, cmdNewInventoryEC2Client(&awsCfg), opCfg.Region, opCfg.AccountID, time.Now())
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory security-groups: %v", err)
		}
		inv.SummaryOnly = inventorySummaryOnly(args)
		return model.Output(cc, env, &inv)
	}
}

// inventoryEKSCmd reports clusters that direct cleanup tags may not discover.
// It is read-only and is intentionally included in every cleanup workflow run.
func inventoryEKSCmd() model.NormalCmd {
	return func(args model.ArgVals, cc *model.Cli, env *model.Env, _ []model.ParsedCmd) error {
		syncVerbose(env)

		opCfg := loadPurgeOperatorConfig(args.GetRaw("region"))
		ctx := context.Background()
		if err := verifyPurgeIdentity(ctx, opCfg); err != nil {
			return err
		}

		awsCfg, err := cmdLoadAWSConfig(ctx, opCfg.Profile, opCfg.Region)
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory: load aws config: %v", err)
		}
		inv, err := cmdInventoryEKS(
			ctx,
			cmdNewInventoryEKSClient(&awsCfg),
			opCfg.Region,
			opCfg.AccountID,
			time.Now(),
		)
		if err != nil {
			return cp9errors.Newf(cp9errors.CategoryResource, "cp9 inventory eks: %v", err)
		}
		inv.SummaryOnly = inventorySummaryOnly(args)
		return model.Output(cc, env, &inv)
	}
}

func inventorySummaryOnly(args model.ArgVals) bool {
	return strings.EqualFold(strings.TrimSpace(args.GetRaw("summary-only")), "true")
}
