//
//  Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

package mcp

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
)

// ServiceConnector implements the Connector interface using in-process
// service layer calls, avoiding HTTP round-trips to self.
type ServiceConnector struct {
	userID       string
	listDatasets func(ctx context.Context, userID string, page, pageSize int, orderby string, desc bool) ([]map[string]interface{}, int64, error)
	listChats    func(ctx context.Context, userID string, page, pageSize int, orderby string, desc bool) ([]map[string]interface{}, int64, error)
	retrieval    func(ctx context.Context, userID string, req RetrievalRequest) (string, error)
}

// NewServiceConnector creates a ServiceConnector.
// The function arguments abstract the service dependencies so this package
// does not import the service layer directly.
func NewServiceConnector(
	userID string,
	listDatasetsFunc func(ctx context.Context, userID string, page, pageSize int, orderby string, desc bool) ([]map[string]interface{}, int64, error),
	listChatsFunc func(ctx context.Context, userID string, page, pageSize int, orderby string, desc bool) ([]map[string]interface{}, int64, error),
	retrievalFunc func(ctx context.Context, userID string, req RetrievalRequest) (string, error),
) *ServiceConnector {
	return &ServiceConnector{
		userID:       userID,
		listDatasets: listDatasetsFunc,
		listChats:    listChatsFunc,
		retrieval:    retrievalFunc,
	}
}

// ListDatasets returns newline-delimited JSON, each line being
// {"id": "...", "description": "..."} for a dataset.
func (c *ServiceConnector) ListDatasets(ctx context.Context, page, pageSize int, orderby string, desc bool) (string, error) {
	data, _, err := c.listDatasets(ctx, c.userID, page, pageSize, orderby, desc)
	if err != nil {
		return "", fmt.Errorf("list datasets: %w", err)
	}

	var lines []string
	for _, d := range data {
		id, _ := d["id"].(string)
		name := ""
		if v, ok := d["name"]; ok {
			if s, ok := v.(string); ok {
				name = s
			}
		}
		desc := ""
		if v, ok := d["description"]; ok {
			if s, ok := v.(string); ok {
				desc = s
			}
		}
		// Match Python output: {"id": "...", "name": "...", "description": "..."}
		item := map[string]interface{}{
			"id":          id,
			"name":        name,
			"description": desc,
		}
		b, err := json.Marshal(item)
		if err != nil {
			continue
		}
		lines = append(lines, string(b))
	}
	return strings.Join(lines, "\n"), nil
}

// ListChats returns newline-delimited JSON, each line being
// {"id": "...", "name": "...", "description": "..."} for a chat assistant.
func (c *ServiceConnector) ListChats(ctx context.Context, page, pageSize int, orderby string, desc bool) (string, error) {
	data, _, err := c.listChats(ctx, c.userID, page, pageSize, orderby, desc)
	if err != nil {
		return "", fmt.Errorf("list chats: %w", err)
	}

	var lines []string
	for _, d := range data {
		id, _ := d["id"].(string)
		name := ""
		if v, ok := d["name"]; ok {
			if s, ok := v.(string); ok {
				name = s
			}
		}
		description := ""
		if v, ok := d["description"]; ok {
			if s, ok := v.(string); ok {
				description = s
			}
		}
		item := map[string]interface{}{
			"id":          id,
			"name":        name,
			"description": description,
		}
		b, err := json.Marshal(item)
		if err != nil {
			continue
		}
		lines = append(lines, string(b))
	}
	return strings.Join(lines, "\n"), nil
}

// Retrieval executes a retrieval via the in-process service and returns
// the result as a JSON string.
func (c *ServiceConnector) Retrieval(ctx context.Context, req RetrievalRequest) (string, error) {
	return c.retrieval(ctx, c.userID, req)
}
