package alicloud

import (
	"context"
	"fmt"

	alivpcv1alpha1 "github.com/crossplane-contrib/provider-upjet-alibabacloud/apis/vpc/v1alpha1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/vpcpeering/task/common"
)

// routeManager implements the RouteManager interface for AliCloud.
// It manages AliCloud VPC RouteEntry CRs for VPC peering connections.
type routeManager struct {
	client             client.Client
	vpcPeering         *v1alpha1.VPCPeering
	providerConfigName string
}

// NewAliCloudRouteManager creates a new AliCloud route manager.
func NewAliCloudRouteManager(
	client client.Client,
	vpcPeering *v1alpha1.VPCPeering,
	providerConfigName string,
) *routeManager {
	return &routeManager{
		client:             client,
		vpcPeering:         vpcPeering,
		providerConfigName: providerConfigName,
	}
}

// ListRoutes lists all RouteEntry CRs associated with a VPC peering.
// It converts AliCloud-specific RouteEntry objects to the unified RouteInfo format.
func (m *routeManager) ListRoutes(ctx context.Context, vpcPeeringName string) ([]common.RouteInfo, error) {
	routeList := &alivpcv1alpha1.RouteEntryList{}
	labelOpt := client.MatchingLabels{
		v1alpha1.VPCPeeringNameKey: vpcPeeringName,
	}

	if err := m.client.List(ctx, routeList, labelOpt); err != nil {
		return nil, fmt.Errorf("failed to list AliCloud routes: %w", err)
	}

	result := make([]common.RouteInfo, 0, len(routeList.Items))
	for _, route := range routeList.Items {
		info := common.RouteInfo{
			Name: route.Name,
			// AliCloud routes don't have a state field like AWS (no blackhole concept)
			State:   "",
			IsReady: controllers.IsResourceReady(route.Status.ResourceStatus),
		}

		// Extract route table name from reference
		if route.Spec.ForProvider.RouteTableIDRef != nil {
			info.RouteTableName = route.Spec.ForProvider.RouteTableIDRef.Name
		}

		result = append(result, info)
	}

	return result, nil
}

// DeleteRoute deletes a single AliCloud RouteEntry CR.
// This operation is idempotent - NotFound errors are ignored.
func (m *routeManager) DeleteRoute(ctx context.Context, route common.RouteInfo) error {
	obj := &alivpcv1alpha1.RouteEntry{
		ObjectMeta: metav1.ObjectMeta{
			Name: route.Name,
		},
	}

	if err := controllers.DeleteUpboundResource(ctx, m.client, obj); err != nil {
		// Ignore NotFound errors for idempotent deletion
		return client.IgnoreNotFound(err)
	}

	return nil
}
