// plexum-minimax-provider-plugin is a Plexum ProviderPlugin that
// serves MiniMax models via MiniMax's Anthropic-compatible endpoint.
//
// Backend is fixed to "api" (per scope): global endpoint
// https://api.minimax.io/anthropic, CN endpoint https://api.minimaxi.com/anthropic.
// Authentication: a single API key sourced from the plugin's config
// file at <profile>/plugins/plexum-minimax-provider/config.json.
//
// Declared models (advertised in manifest.contracts.provider.models):
//   - MiniMax-M2.7
//   - MiniMax-M2.7-highspeed
//
// Operator points an agent at one of these via agent.json.model and
// Plexum's ProviderRouter dispatches each turn here.
package main

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"os"
	"path/filepath"

	"git.hangman-lab.top/hzhang/Plexum-sdk-go/canonical"
	plugin "git.hangman-lab.top/hzhang/Plexum-sdk-go/plugin"

	"git.hangman-lab.top/hzhang/Plexum-anthropic-compat-client/anthropic"
	"git.hangman-lab.top/hzhang/Plexum-anthropic-compat-client/translate"
)

const (
	pluginName = "plexum-minimax-provider"

	defaultBaseURLGlobal = "https://api.minimax.io/anthropic"
	defaultBaseURLCN     = "https://api.minimaxi.com/anthropic"
	defaultMaxTokens     = 4096 // MiniMax M2.7 can serve up to 131072 — but most turns want less
)

// supportedModels = what the manifest's provider.models advertises.
// Operator agent.json.model values must match one of these.
var supportedModels = []string{"MiniMax-M2.7", "MiniMax-M2.7-highspeed"}

// HostConfig is the per-profile plugin config at
// <profile>/plugins/plexum-minimax-provider/config.json:
//
//	{
//	  "api_key":  "sk-cp-...",       // required
//	  "region":   "global" | "cn",   // default "global"
//	  "base_url": "https://...",     // optional override
//	  "max_tokens_default": 4096     // optional default when TurnRequest.MaxTokens unset
//	}
type HostConfig struct {
	APIKey            string `json:"api_key"`
	Region            string `json:"region"`
	BaseURL           string `json:"base_url"`
	MaxTokensDefault  int    `json:"max_tokens_default"`
}

type minimaxPlugin struct {
	host plugin.HostAPI
	cfg  HostConfig
	cli  *anthropic.Client
}

func (p *minimaxPlugin) Manifest() plugin.Manifest {
	return plugin.Manifest{
		Name:       pluginName,
		Version:    "0.1.0",
		Activation: plugin.ActivationLazy,
		Executable: "plexum-minimax-provider-plugin",
		Contracts: plugin.Contracts{
			Provider: &plugin.ProviderContract{Models: supportedModels},
		},
	}
}

func (p *minimaxPlugin) Init(ctx context.Context, host plugin.HostAPI) error {
	p.host = host

	profileRoot := os.Getenv("PLEXUM_PROFILE_ROOT")
	if profileRoot == "" {
		home, _ := os.UserHomeDir()
		profileRoot = filepath.Join(home, ".plexum")
	}
	cfgPath := filepath.Join(profileRoot, "plugins", pluginName, "config.json")
	raw, err := os.ReadFile(cfgPath)
	if err != nil && !errors.Is(err, os.ErrNotExist) {
		return fmt.Errorf("read %s: %w", cfgPath, err)
	}
	if len(raw) > 0 {
		if err := json.Unmarshal(raw, &p.cfg); err != nil {
			return fmt.Errorf("parse %s: %w", cfgPath, err)
		}
	}
	if p.cfg.APIKey == "" {
		return fmt.Errorf("minimax: api_key missing in %s", cfgPath)
	}
	base := p.cfg.BaseURL
	if base == "" {
		if p.cfg.Region == "cn" {
			base = defaultBaseURLCN
		} else {
			base = defaultBaseURLGlobal
		}
	}
	if p.cfg.MaxTokensDefault <= 0 {
		p.cfg.MaxTokensDefault = defaultMaxTokens
	}
	p.cli = anthropic.New(base, p.cfg.APIKey)
	host.Log("info", "minimax provider initialized", map[string]any{
		"base": base, "models": supportedModels,
		"max_tokens_default": p.cfg.MaxTokensDefault,
	})
	return nil
}

// Stream is the ProviderPlugin entrypoint. canonical.TurnRequest in,
// channel of canonical.TurnEvent out (plugin author owns + closes the
// channel; SDK forwards the stream over MCP notifications).
func (p *minimaxPlugin) Stream(ctx context.Context, modelID string, req canonical.TurnRequest) (<-chan canonical.TurnEvent, error) {
	apiReq, err := translate.CanonicalToAnthropic(req, modelID, p.cfg.MaxTokensDefault)
	if err != nil {
		return nil, err
	}
	raw, err := p.cli.StreamMessages(ctx, apiReq)
	if err != nil {
		return nil, err
	}
	out := make(chan canonical.TurnEvent, 32)
	go func() {
		defer close(out)
		tr := translate.NewTranslator()
		for ev := range raw {
			for _, te := range tr.Translate(ev) {
				select {
				case out <- te:
				case <-ctx.Done():
					return
				}
			}
		}
	}()
	return out, nil
}

func main() {
	if err := plugin.Serve(&minimaxPlugin{}); err != nil {
		fmt.Fprintf(os.Stderr, "plexum-minimax-provider-plugin: %v\n", err)
		os.Exit(1)
	}
}
