package main

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strings"

	"github.com/mattermost/mattermost/server/public/plugin"
)

const kvPrefix = "ls_session_"

// SessionData represents a tracked agent session.
type SessionData struct {
	SessionKey  string        `json:"session_key"`
	PostID      string        `json:"post_id"`
	ChannelID   string        `json:"channel_id"`
	RootID      string        `json:"root_id,omitempty"`
	AgentID     string        `json:"agent_id"`
	Status      string        `json:"status"` // active, done, error, interrupted
	Lines       []string      `json:"lines"`
	ElapsedMs   int64         `json:"elapsed_ms"`
	TokenCount  int           `json:"token_count"`
	Children    []SessionData `json:"children,omitempty"`
	StartTimeMs int64         `json:"start_time_ms"`
}

// Store wraps Mattermost KV store operations for session persistence.
type Store struct {
	api plugin.API
}

// NewStore creates a new Store instance.
func NewStore(api plugin.API) *Store {
	return &Store{api: api}
}

// encodeKey URL-encodes a session key for safe KV storage.
func encodeKey(sessionKey string) string {
	return kvPrefix + url.PathEscape(sessionKey)
}

// SaveSession stores a session in the KV store.
func (s *Store) SaveSession(sessionKey string, data SessionData) error {
	b, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("marshal session: %w", err)
	}
	appErr := s.api.KVSet(encodeKey(sessionKey), b)
	if appErr != nil {
		return fmt.Errorf("kv set: %s", appErr.Error())
	}
	return nil
}

// GetSession retrieves a session from the KV store.
func (s *Store) GetSession(sessionKey string) (*SessionData, error) {
	b, appErr := s.api.KVGet(encodeKey(sessionKey))
	if appErr != nil {
		return nil, fmt.Errorf("kv get: %s", appErr.Error())
	}
	if b == nil {
		return nil, nil
	}
	var data SessionData
	if err := json.Unmarshal(b, &data); err != nil {
		return nil, fmt.Errorf("unmarshal session: %w", err)
	}
	return &data, nil
}

// DeleteSession removes a session from the KV store.
func (s *Store) DeleteSession(sessionKey string) error {
	appErr := s.api.KVDelete(encodeKey(sessionKey))
	if appErr != nil {
		return fmt.Errorf("kv delete: %s", appErr.Error())
	}
	return nil
}

// ListActiveSessions returns all active sessions from the KV store.
func (s *Store) ListActiveSessions() ([]SessionData, error) {
	var sessions []SessionData
	page := 0
	perPage := 100

	for {
		keys, appErr := s.api.KVList(page, perPage)
		if appErr != nil {
			return nil, fmt.Errorf("kv list: %s", appErr.Error())
		}
		if len(keys) == 0 {
			break
		}

		for _, key := range keys {
			if !strings.HasPrefix(key, kvPrefix) {
				continue
			}
			b, getErr := s.api.KVGet(key)
			if getErr != nil || b == nil {
				continue
			}
			var data SessionData
			if err := json.Unmarshal(b, &data); err != nil {
				continue
			}
			if data.Status == "active" {
				sessions = append(sessions, data)
			}
		}
		page++
	}

	return sessions, nil
}
