package service import ( "fmt" "github.com/google/uuid" "github.com/picoclaw/chart/internal/renderer" "github.com/picoclaw/chart/internal/types" ) type ChartService struct { svgRenderer *renderer.SVGRenderer pngRenderer *renderer.PNGRenderer ansiRenderer *renderer.ANSIRenderer textRenderer *renderer.TextRenderer chartCache map[string]*types.Chart } func NewChartService() *ChartService { return &ChartService{ svgRenderer: renderer.NewSVGRenderer(), pngRenderer: renderer.NewPNGRenderer(), ansiRenderer: renderer.NewANSIRenderer(), textRenderer: renderer.NewTextRenderer(), chartCache: make(map[string]*types.Chart), } } func (s *ChartService) CreateChart(req *types.ChartRequest) (*types.ChartResponse, error) { chart := &types.Chart{ ID: uuid.New().String(), Type: req.Type, Title: req.Title, Data: req.Data, } svgData, err := s.svgRenderer.Render(chart) if err != nil { return nil, fmt.Errorf("failed to render SVG: %w", err) } chart.SVG = svgData pngData, err := s.pngRenderer.Render(chart) if err != nil { return nil, fmt.Errorf("failed to render PNG: %w", err) } chart.PNG = pngData ansiData, err := s.ansiRenderer.Render(chart) if err != nil { return nil, fmt.Errorf("failed to render ANSI: %w", err) } textData, err := s.textRenderer.Render(chart) if err != nil { return nil, fmt.Errorf("failed to render text: %w", err) } s.chartCache[chart.ID] = chart return &types.ChartResponse{ ChartID: chart.ID, Text: string(textData), ANSI: string(ansiData), SVG: string(chart.SVG), PNGURL: fmt.Sprintf("/api/v1/chart/%s.png", chart.ID), Markdown: fmt.Sprintf("![%s](/api/v1/chart/%s.png)", chart.Title, chart.ID), }, nil } func (s *ChartService) GetChart(id string) (*types.Chart, error) { chart, ok := s.chartCache[id] if !ok { return nil, fmt.Errorf("chart not found: %s", id) } return chart, nil } func (s *ChartService) GetChartPNG(id string) ([]byte, error) { chart, err := s.GetChart(id) if err != nil { return nil, err } return chart.PNG, nil }