package service

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"strings"
	"time"

	caasmmodel "security-center-backend/internal/modules/caasm/model"
	"security-center-backend/internal/modules/caasm/parser"
	"security-center-backend/internal/modules/caasm/repository"
)

const defaultAPIRoutePreviewLimit = 50

type APIRouteAssetService struct {
	repo repository.APIRouteAssetRepository
}

type APIRouteAssetListResult struct {
	Items []caasmmodel.APIRouteAsset
	Total int64
}

type APIRouteConfigInput struct {
	Name     string
	RawYAML  string
	ActorID  *uint64
	PreviewN int
}

type APIRouteConfigSummary struct {
	ID          uint64     `json:"id"`
	Name        string     `json:"name"`
	SourceType  string     `json:"source_type"`
	YAMLSHA256  string     `json:"yaml_sha256"`
	Status      string     `json:"status"`
	RouteCount  int        `json:"route_count"`
	UploadedBy  *uint64    `json:"uploaded_by,omitempty"`
	IsActive    bool       `json:"is_active"`
	ActivatedAt *time.Time `json:"activated_at,omitempty"`
	CreatedAt   time.Time  `json:"created_at"`
	UpdatedAt   time.Time  `json:"updated_at"`
}

type APIRouteConfigPreview struct {
	Name       string                     `json:"name"`
	YAMLSHA256 string                     `json:"yaml_sha256"`
	RouteCount int                        `json:"route_count"`
	Preview    []caasmmodel.APIRouteAsset `json:"preview"`
	Config     *APIRouteConfigSummary     `json:"config,omitempty"`
	Error      string                     `json:"error,omitempty"`
}

func NewAPIRouteAssetService(repo repository.APIRouteAssetRepository) *APIRouteAssetService {
	return &APIRouteAssetService{repo: repo}
}

func (s *APIRouteAssetService) List(ctx context.Context, filter repository.APIRouteAssetFilter, page, pageSize int) (*APIRouteAssetListResult, error) {
	if s.repo == nil {
		return &APIRouteAssetListResult{}, nil
	}
	items, total, err := s.repo.ListActive(ctx, filter, page, pageSize)
	if err != nil {
		return nil, err
	}
	return &APIRouteAssetListResult{Items: items, Total: total}, nil
}

func (s *APIRouteAssetService) ActiveConfig(ctx context.Context) (*APIRouteConfigSummary, error) {
	if s.repo == nil {
		return nil, errors.New("api route asset repository is not configured")
	}
	config, err := s.repo.FindActiveConfig(ctx)
	if err != nil || config == nil {
		return nil, err
	}
	return summarizeAPIRouteConfig(config), nil
}

func (s *APIRouteAssetService) Preview(ctx context.Context, input APIRouteConfigInput) (*APIRouteConfigPreview, error) {
	_ = ctx
	rawYAML := strings.TrimSpace(input.RawYAML)
	if rawYAML == "" {
		return nil, errors.New("raw_yaml is required")
	}
	parsed, err := parser.ParseKongYAML(rawYAML)
	if err != nil {
		return &APIRouteConfigPreview{
			Name:       defaultAPIRouteConfigName(input.Name),
			YAMLSHA256: sha256Hex(rawYAML),
			Error:      err.Error(),
		}, nil
	}
	limit := input.PreviewN
	if limit <= 0 {
		limit = defaultAPIRoutePreviewLimit
	}
	if limit > len(parsed.Assets) {
		limit = len(parsed.Assets)
	}
	preview := append([]caasmmodel.APIRouteAsset(nil), parsed.Assets[:limit]...)
	return &APIRouteConfigPreview{
		Name:       defaultAPIRouteConfigName(input.Name),
		YAMLSHA256: sha256Hex(rawYAML),
		RouteCount: len(parsed.Assets),
		Preview:    preview,
	}, nil
}

func (s *APIRouteAssetService) SaveActiveConfig(ctx context.Context, input APIRouteConfigInput) (*APIRouteConfigSummary, error) {
	if s.repo == nil {
		return nil, errors.New("api route asset repository is not configured")
	}
	rawYAML := strings.TrimSpace(input.RawYAML)
	if rawYAML == "" {
		return nil, errors.New("raw_yaml is required")
	}
	parsed, err := parser.ParseKongYAML(rawYAML)
	if err != nil {
		return nil, err
	}
	config := &caasmmodel.APIRouteConfig{
		Name:       defaultAPIRouteConfigName(input.Name),
		RawYAML:    rawYAML,
		YAMLSHA256: sha256Hex(rawYAML),
		UploadedBy: input.ActorID,
	}
	if err := s.repo.ReplaceActiveConfig(ctx, config, parsed.Assets); err != nil {
		return nil, err
	}
	return summarizeAPIRouteConfig(config), nil
}

func summarizeAPIRouteConfig(config *caasmmodel.APIRouteConfig) *APIRouteConfigSummary {
	if config == nil {
		return nil
	}
	return &APIRouteConfigSummary{
		ID:          config.ID,
		Name:        config.Name,
		SourceType:  config.SourceType,
		YAMLSHA256:  config.YAMLSHA256,
		Status:      config.Status,
		RouteCount:  config.RouteCount,
		UploadedBy:  config.UploadedBy,
		IsActive:    config.IsActive,
		ActivatedAt: config.ActivatedAt,
		CreatedAt:   config.CreatedAt,
		UpdatedAt:   config.UpdatedAt,
	}
}

func defaultAPIRouteConfigName(name string) string {
	name = strings.TrimSpace(name)
	if name != "" {
		return name
	}
	return "Kong route config " + time.Now().Format("2006-01-02 15:04")
}

func sha256Hex(value string) string {
	sum := sha256.Sum256([]byte(value))
	return hex.EncodeToString(sum[:])
}
