package receipt

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"fmt"

	"github.com/jmoiron/sqlx"
)

type Store struct {
	db *sqlx.DB
}

func NewStore(db *sqlx.DB) *Store {
	return &Store{db: db}
}

// Insert records every HTTP delivery, including retries. Event-level
// idempotency prevents repeated deliveries from producing repeated lifecycle
// observations, while receipts retain evidence that a retry happened.
func (s *Store) Insert(ctx context.Context, in *NewReceipt) (*Receipt, error) {
	groupLabels, err := json.Marshal(in.GroupLabels)
	if err != nil {
		return nil, fmt.Errorf("marshal group labels: %w", err)
	}
	commonLabels, err := json.Marshal(in.CommonLabels)
	if err != nil {
		return nil, fmt.Errorf("marshal common labels: %w", err)
	}
	commonAnnotations, err := json.Marshal(in.CommonAnnotations)
	if err != nil {
		return nil, fmt.Errorf("marshal common annotations: %w", err)
	}
	sum := sha256.Sum256(in.RawPayload)
	payloadHash := hex.EncodeToString(sum[:])

	const q = `
		INSERT INTO am_webhook_receipt (
			group_key, receiver, status, group_labels, common_labels,
			common_annotations, external_url, truncated_alerts,
			notification_reason, payload_hash, raw_payload
		) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
	`
	res, err := s.db.ExecContext(ctx, q,
		in.GroupKey, in.Receiver, in.Status, groupLabels, commonLabels,
		commonAnnotations, in.ExternalURL, in.TruncatedAlerts,
		in.NotificationReason, payloadHash, in.RawPayload,
	)
	if err != nil {
		return nil, fmt.Errorf("insert webhook receipt: %w", err)
	}
	id, err := res.LastInsertId()
	if err != nil {
		return nil, fmt.Errorf("get webhook receipt id: %w", err)
	}
	return s.GetByID(ctx, id)
}

func (s *Store) GetByID(ctx context.Context, id int64) (*Receipt, error) {
	const q = `SELECT * FROM am_webhook_receipt WHERE id = ?`
	var r Receipt
	if err := s.db.GetContext(ctx, &r, q, id); err != nil {
		return nil, fmt.Errorf("get webhook receipt: %w", err)
	}
	return &r, nil
}
