package blossom

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"io"
	"net/http"
	"time"
)

type Client struct {
	serverURL  string
	httpClient *http.Client
}

type BlossomResponse struct {
	Hash string `json:"hash"`
}

func NewClient(serverURL string) *Client {
	return &Client{
		serverURL: serverURL,
		httpClient: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}

func (c *Client) Put(data []byte) (string, error) {
	url := c.serverURL + "/upload"
	
	req, err := http.NewRequest("PUT", url, bytes.NewReader(data))
	if err != nil {
		return "", fmt.Errorf("error creating PUT request: %w", err)
	}

	req.Header.Set("Content-Type", "application/octet-stream")
	req.Header.Set("Content-Length", fmt.Sprintf("%d", len(data)))

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return "", fmt.Errorf("error executing PUT request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return "", fmt.Errorf("PUT request failed with status %d: %s", resp.StatusCode, string(body))
	}

	// Calculate SHA-256 hash
	hasher := sha256.New()
	hasher.Write(data)
	hash := fmt.Sprintf("%x", hasher.Sum(nil))
	return hash, nil
}

func (c *Client) Get(hash string) ([]byte, error) {
	url := c.serverURL + "/" + hash

	resp, err := c.httpClient.Get(url)
	if err != nil {
		return nil, fmt.Errorf("error executing GET request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("GET request failed with status %d", resp.StatusCode)
	}

	data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("error reading response body: %w", err)
	}

	return data, nil
}

// MockClient for testing without a real Blossom server
type MockClient struct {
	storage map[string][]byte
}

func NewMockClient() *MockClient {
	return &MockClient{
		storage: make(map[string][]byte),
	}
}

func (m *MockClient) Put(data []byte) (string, error) {
	// Calculate SHA-256 hash
	hasher := sha256.New()
	hasher.Write(data)
	hash := fmt.Sprintf("%x", hasher.Sum(nil))
	m.storage[hash] = data
	return hash, nil
}

func (m *MockClient) Get(hash string) ([]byte, error) {
	data, exists := m.storage[hash]
	if !exists {
		return nil, fmt.Errorf("blob not found: %s", hash)
	}
	return data, nil
}