package bridge

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"strconv"
	"time"
)

const (
	ccipTimeout    = 5 * time.Second
	defaultCCIPFee = "100000000000000000" // ~0.1 LINK (18 decimals)
)

type ccipQuoteResponse struct {
	Fee string `json:"fee"`
}

// CCIPProvider implements Provider for Chainlink CCIP
type CCIPProvider struct {
	quoteURL string
	client   *http.Client
	cfg      *Config
}

// NewCCIPProvider creates a new CCIP bridge provider. cfg can be nil (uses DefaultConfig).
func NewCCIPProvider(cfg *Config) *CCIPProvider {
	if cfg == nil {
		cfg = DefaultConfig()
	}
	quoteURL := os.Getenv("CCIP_ROUTER_QUOTE_URL")
	return &CCIPProvider{
		quoteURL: quoteURL,
		client:   &http.Client{Timeout: ccipTimeout},
		cfg:      cfg,
	}
}

func (p *CCIPProvider) Name() string { return "CCIP" }

func (p *CCIPProvider) SupportsRoute(fromChain, toChain int) bool {
	return p.cfg.SupportsCCIPRoute(fromChain, toChain)
}

func (p *CCIPProvider) GetQuote(ctx context.Context, req *BridgeRequest) (*BridgeQuote, error) {
	if !p.SupportsRoute(req.FromChain, req.ToChain) {
		return nil, fmt.Errorf("CCIP: unsupported route %d -> %d", req.FromChain, req.ToChain)
	}

	fee := defaultCCIPFee
	if p.quoteURL != "" {
		body, err := json.Marshal(map[string]interface{}{
			"sourceChain": req.FromChain,
			"destChain":   req.ToChain,
			"token":       req.FromToken,
			"amount":      req.Amount,
		})
		if err == nil {
			httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.quoteURL, bytes.NewReader(body))
			if err == nil {
				httpReq.Header.Set("Content-Type", "application/json")
				resp, err := p.client.Do(httpReq)
				if err == nil && resp != nil {
					defer resp.Body.Close()
					if resp.StatusCode == http.StatusOK {
						var r ccipQuoteResponse
						if json.NewDecoder(resp.Body).Decode(&r) == nil && r.Fee != "" {
							fee = r.Fee
						}
					}
				}
			}
		}
	}

	return &BridgeQuote{
		Provider:      "CCIP",
		FromChain:     req.FromChain,
		ToChain:       req.ToChain,
		FromAmount:    req.Amount,
		ToAmount:      req.Amount,
		Fee:           fee,
		EstimatedTime: "5-15 min",
		Route: []BridgeStep{
			{Provider: "CCIP", From: strconv.Itoa(req.FromChain), To: strconv.Itoa(req.ToChain), Type: "bridge"},
		},
	}, nil
}
