package pretix

import (
	"context"
	"database/sql"
	"fmt"
	"io"
	"log"
	"net/http"
	"strings"
	"sync"

	"git.luj0ga.de/franconian/matrix-pretix/internal/config"
	"git.luj0ga.de/franconian/matrix-pretix/internal/matrix"
)

type Server struct {
	client	http.Client
	config	*config.ServerConfig
	db	*sql.DB
	matrix	*matrix.Client
}

func NewServer(config *config.ServerConfig, db *sql.DB, matrix *matrix.Client) *Server {
	return &Server{
		config: config,
		db:	db,
		matrix: matrix,
	}
}

func (s Server) ListenAndServe(ctx context.Context, wg *sync.WaitGroup) error {
	err := s.createTables()
	if err != nil {
		return err
	}

	http.HandleFunc("/", http.NotFound)
	http.HandleFunc("/order_placed", s.orderPlaced)

	server := http.Server{
		Addr:	s.config.ListenAddress,
	}

	go func() {
		wg.Add(1)
		defer wg.Done()

		<-ctx.Done()

		err := server.Shutdown(context.Background())
		if err != nil {
			log.Print(err)
		}
	}()

	log.Print("listening on ", s.config.ListenAddress)

	err = server.ListenAndServe()
	if err != http.ErrServerClosed {
		return err
	}

	return nil
}

func (s Server) createTables() error {
	tables := []string{
		`CREATE TABLE IF NOT EXISTS orders (
			code	TEXT	PRIMARY KEY ON CONFLICT IGNORE
		);
		`,
	}

	tx, err := s.db.Begin()
	if err != nil {
		return err
	}

	for _, table := range tables {
		_, err := tx.Exec(table)
		if err != nil {
			if err := tx.Rollback(); err != nil {
				log.Print(err)
			}

			return err
		}
	}

	err = tx.Commit()
	if err != nil {
		return err
	}

	return nil
}

func (s Server) buildURL(endpoint string, args ...any) string {
	baseURL := strings.TrimSuffix(s.config.BaseURL, "/")
	return fmt.Sprintf(endpoint, append([]any{baseURL}, args...)...)
}

func writeStatus(w http.ResponseWriter, code int) {
	w.WriteHeader(code)
	io.WriteString(w, http.StatusText(code))
}
