package webhook

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"

	"wedding-server/internal/config"
	"wedding-server/internal/store"
)

type Client struct {
	cfg        config.WebhookConfig
	httpClient *http.Client
}

func New(cfg config.WebhookConfig) *Client {
	return &Client{
		cfg:        cfg,
		httpClient: &http.Client{Timeout: time.Duration(cfg.TimeoutSeconds) * time.Second},
	}
}

func (c *Client) post(url, event string, data any) error {
	if url == "" {
		return nil
	}

	body, err := json.Marshal(map[string]any{
		"event":  event,
		"sentAt": time.Now().UTC(),
		"data":   data,
	})
	if err != nil {
		return err
	}

	req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
	if err != nil {
		return err
	}
	req.Header.Set("Content-Type", "application/json")
	for k, v := range c.cfg.Headers {
		req.Header.Set(k, v)
	}
	if c.cfg.Secret != "" {
		req.Header.Set("X-Webhook-Signature", sign(c.cfg.Secret, body))
	}

	resp, err := c.httpClient.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	io.Copy(io.Discard, resp.Body)

	if resp.StatusCode >= 300 {
		return fmt.Errorf("webhook %s: unexpected status %d", url, resp.StatusCode)
	}
	return nil
}

func sign(secret string, body []byte) string {
	mac := hmac.New(sha256.New, []byte(secret))
	mac.Write(body)
	return "sha256=" + hex.EncodeToString(mac.Sum(nil))
}

func (c *Client) SendRSVP(r store.RSVP) error {
	guests := make([]map[string]any, len(r.Guests))
	for i, g := range r.Guests {
		guests[i] = map[string]any{"name": g.Name, "isChild": g.IsChild}
	}
	return c.post(c.cfg.RSVPURL, "rsvp.created", map[string]any{
		"guests":  guests,
		"message": r.Message,
	})
}

func (c *Client) SendPhotoUpload(u store.PhotoUpload, files []store.PhotoFile) error {
	urls := make([]string, len(files))
	for i, f := range files {
		urls[i] = f.URL
	}
	return c.post(c.cfg.PhotoURL, "photos.uploaded", map[string]any{
		"name":      u.Name,
		"message":   u.Message,
		"email":     u.Email,
		"phone":     u.Phone,
		"photoUrls": urls,
	})
}
