package agent

import (
	"time"

	"security-center-backend/internal/model"
)

// CreateAPIKeyRequest is the contract for POST /agent/api-keys (plan §2.3).
// OwnerUserID is never accepted from the client: ownership is forced to the
// current authenticated user by the handler.
type CreateAPIKeyRequest struct {
	AgentName       string     `json:"agent_name" binding:"required"`
	PermissionScope []string   `json:"permission_scope"`
	ExpiresAt       *time.Time `json:"expires_at"`
}

// APIKeyResponse is the sanitized view of an API key. It never contains
// KeyHash or any plaintext key material.
type APIKeyResponse struct {
	ID              uint64     `json:"id"`
	AgentName       string     `json:"agent_name"`
	KeyPrefix       string     `json:"key_prefix"`
	PermissionScope []string   `json:"permission_scope"`
	Status          string     `json:"status"` // active | revoked | expired (display state)
	ExpiresAt       *time.Time `json:"expires_at,omitempty"`
	LastUsedAt      *time.Time `json:"last_used_at,omitempty"`
	CreatedAt       time.Time  `json:"created_at"`
	OwnerUserID     uint64     `json:"owner_user_id"`
	OwnerName       string     `json:"owner_name,omitempty"`
	OwnerEmail      string     `json:"owner_email,omitempty"`
}

// CreateAPIKeyResponse is returned exactly once on creation/rotation: APIKey
// carries the plaintext key and is never shown again afterwards.
type CreateAPIKeyResponse struct {
	APIKeyResponse
	APIKey string `json:"api_key"`
}

// APIKeyUsageDailyCount is one day's call volume in the usage window.
type APIKeyUsageDailyCount struct {
	Date  string `json:"date"` // YYYY-MM-DD (server local time)
	Count int64  `json:"count"`
}

// APIKeyUsageResourceCount is the call volume for one resource_type
// (audit_logs.resource_type, e.g. "vulnerabilities") in the usage window.
type APIKeyUsageResourceCount struct {
	ResourceType string `json:"resource_type"`
	Count        int64  `json:"count"`
}

// APIKeyUsage is the contract for GET /agent/api-keys/:id/usage (plan §5.3).
// It aggregates audit_logs rows attributed to the key (actor_type='agent',
// metadata.agent_id = key id) over the requested window. Note the retention
// caveat: audit data older than audit.retention_days (default 90) is purged,
// so the window can never reach further back than that.
type APIKeyUsage struct {
	DailyCounts       []APIKeyUsageDailyCount    `json:"daily_counts"`
	ResourceBreakdown []APIKeyUsageResourceCount `json:"resource_breakdown"`
	TotalCalls        int64                      `json:"total_calls"`
	LastUsedAt        *time.Time                 `json:"last_used_at"`
	WindowDays        int                        `json:"window_days"`
}

// toAPIKeyResponse converts a stored record to its sanitized response form.
// A key still marked active in the DB but past ExpiresAt is reported as
// "expired" (plan §1.2 note: expired is a logical, not stored, state).
func toAPIKeyResponse(key *model.APIKey) *APIKeyResponse {
	if key == nil {
		return nil
	}
	status := string(key.Status)
	if key.Status == model.APIKeyStatusActive && key.ExpiresAt != nil && key.ExpiresAt.Before(time.Now()) {
		status = string(model.APIKeyStatusExpired)
	}
	scope := make([]string, len(key.PermissionScope))
	copy(scope, key.PermissionScope)
	resp := &APIKeyResponse{
		ID:              key.ID,
		AgentName:       key.AgentName,
		KeyPrefix:       key.KeyPrefix,
		PermissionScope: scope,
		Status:          status,
		ExpiresAt:       key.ExpiresAt,
		LastUsedAt:      key.LastUsedAt,
		CreatedAt:       key.CreatedAt,
		OwnerUserID:     key.OwnerUserID,
	}
	if key.Owner != nil {
		resp.OwnerName = key.Owner.Name
		resp.OwnerEmail = key.Owner.Email
	}
	return resp
}
