package main

import (
	"context"
	"fmt"
	"log"
	"net"
	"os"
	"sync"
	"time"

	"addition-service/generated"

	"google.golang.org/grpc"
)

type additionServer struct {
	generated.UnimplementedCalculatorServer
	operations []*generated.Operation
	mutex      sync.RWMutex
}

func (s *additionServer) Add(ctx context.Context, req *generated.Numbers) (*generated.Result, error) {
	result := req.A + req.B
	
	op := &generated.Operation{
		Type:      "ADDITION",
		A:         req.A,
		B:         req.B,
		Result:    result,
		Timestamp: time.Now().Format("2006-01-02 15:04:05"),
	}
	
	s.mutex.Lock()
	s.operations = append(s.operations, op)
	s.mutex.Unlock()
	
	go s.logToFile(op)
	
	fmt.Printf(" Addition operation: %d + %d = %d\n", req.A, req.B, result)
	
	return &generated.Result{
		Value:     result,
		Operation: "ADDITION",
	}, nil
}

func (s *additionServer) GetOperationHistory(req *generated.Empty, stream generated.Calculator_GetOperationHistoryServer) error {
	s.mutex.RLock()
	defer s.mutex.RUnlock()
	
	history := &generated.OperationHistory{
		ServiceName: "Addition Service",
		Operations:  s.operations,
	}
	
	if err := stream.Send(history); err != nil {
		return err
	}
	
	return nil
}

func (s *additionServer) logToFile(op *generated.Operation) {
	file, err := os.OpenFile("operation_log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Printf("Failed to open log file: %v", err)
		return
	}
	defer file.Close()
	
	logEntry := fmt.Sprintf("[%s] %s: %d + %d = %d\n", 
		op.Timestamp, op.Type, op.A, op.B, op.Result)
	
	if _, err := file.WriteString(logEntry); err != nil {
		log.Printf("Failed to write to log file: %v", err)
	}
}

func main() {
	lis, err := net.Listen("tcp", ":50052")
	if err != nil {
		log.Fatalf("Failed to listen: %v", err)
	}
	
	server := grpc.NewServer()
	additionServer := &additionServer{
		operations: make([]*generated.Operation, 0),
	}
	
	generated.RegisterCalculatorServer(server, additionServer)
	
	fmt.Println(" Addition Service running on port 50052")
	fmt.Println(" Ready to receive addition requests...")
	
	if err := server.Serve(lis); err != nil {
		log.Fatalf("Failed to serve: %v", err)
	}
}