package products

import (
	"fmt"
	pb "sipro-mps/api/generated/v1/yandexmarket/products"
	"sipro-mps/internal/marketplace"

	"google.golang.org/grpc"
)

type AdapterGRPC struct {
	pb.UnimplementedProductsServiceServer
	repo Repository
}

func NewAdapterGRPC(repo Repository) *AdapterGRPC {
	return &AdapterGRPC{
		repo: repo,
	}
}

func RegisterAdapterGRPC(server *grpc.Server, marketplacesRepository marketplace.Repository) (*Repository, error) {
	repo := NewAPIRepository(marketplacesRepository)
	adapter := NewAdapterGRPC(repo)
	pb.RegisterProductsServiceServer(server, adapter)
	return &repo, nil
}

func (a *AdapterGRPC) GetProducts(req *pb.GetProductsRequest, stream pb.ProductsService_GetProductsServer) error {
	ctx := stream.Context()
	fmt.Printf("GetProducts called with marketplace_id: %d, offer_ids count: %d\n", req.MarketplaceId, len(req.OfferIds))

	resultChan := make(chan []*pb.GetProductsResponse_Offer, 10)
	errChan := make(chan error)

	go a.repo.GetProducts(ctx, int(req.MarketplaceId), req, resultChan, errChan)

	for {
		select {
		case <-ctx.Done():
			fmt.Println("GetProducts: context cancelled or deadline exceeded:", ctx.Err())
			return ctx.Err()
		case offers, ok := <-resultChan:
			if !ok {
				fmt.Println("GetProducts: result channel closed")
				return nil
			}
			// Send offers in response
			response := &pb.GetProductsResponse{
				Offers: offers,
			}
			if err := stream.Send(response); err != nil {
				fmt.Println("GetProducts: error sending response:", err)
				return err
			}
		case err, ok := <-errChan:
			if !ok {
				return nil
			}
			if err != nil {
				fmt.Println("GetProducts: error received from channel:", err)
				return err
			}
		}
	}
}

func (a *AdapterGRPC) CalculateProductTariffs(req *pb.CalculateProductTariffsRequest, stream pb.ProductsService_CalculateProductTariffsServer) error {
	ctx := stream.Context()
	fmt.Printf("CalculateProductTariffs called with marketplace_id: %d, offers count: %d\n", req.MarketplaceId, len(req.Offers))

	resultChan := make(chan []*pb.CalculateProductTariffsResponse, 10)
	errChan := make(chan error)

	go a.repo.CalculateProductTariffs(ctx, int(req.MarketplaceId), req, resultChan, errChan)

	for {
		select {
		case <-ctx.Done():
			fmt.Println("CalculateProductTariffs: context cancelled or deadline exceeded:", ctx.Err())
			return ctx.Err()
		case responses, ok := <-resultChan:
			if !ok {
				fmt.Println("CalculateProductTariffs: result channel closed")
				return nil
			}
			for _, response := range responses {
				if err := stream.Send(response); err != nil {
					fmt.Println("CalculateProductTariffs: error sending response:", err)
					return err
				}
			}
		case err, ok := <-errChan:
			if !ok {
				return nil
			}
			if err != nil {
				fmt.Println("CalculateProductTariffs: error received from channel:", err)
				return err
			}
		}
	}
}
