package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"

	"github.com/getsentry/sentry-go"

	"github.com/rjNemo/rentease/assets"
	"github.com/rjNemo/rentease/internal/config"
	"github.com/rjNemo/rentease/internal/driver/database"
	"github.com/rjNemo/rentease/internal/driver/parser"
	"github.com/rjNemo/rentease/internal/driver/pdf"
	bookingRepo "github.com/rjNemo/rentease/internal/repository/booking"
	"github.com/rjNemo/rentease/internal/server"
	"github.com/rjNemo/rentease/internal/service/auth"
	"github.com/rjNemo/rentease/internal/service/booking"
)

func main() {
	ctx := context.Background()

	if err := run(ctx); err != nil {
		fmt.Fprintf(os.Stderr, "%s\n", err)
		os.Exit(1)
	}
}

func run(c context.Context) error {
	ctx, cancel := signal.NotifyContext(c, os.Interrupt)
	defer cancel()

	appConfig, err := config.New(ctx)
	if err != nil {
		return err
	}

	// init sentry
	if err := sentry.Init(sentry.ClientOptions{
		Dsn:              appConfig.SentryDsn,
		EnableTracing:    true,
		TracesSampleRate: 1.0,
	}); err != nil {
		return fmt.Errorf("error initializing sentry %w", err)
	}

	// init database
	db, err := database.New(appConfig.DatabaseUrl)
	if err != nil {
		return fmt.Errorf("error connecting to the database %w", err)
	}

	if err = database.Migrate(db, &booking.Booking{}, &booking.Item{}, &booking.Payment{}); err != nil {
		return fmt.Errorf("error migrating the database %w", err)
	}

	bookingStore := bookingRepo.NewPgStore(db)

	// gc, err := calendar.NewGoogleClient(ctx, appConfig.CalendarCredentials)
	// if err != nil {
	// 	return fmt.Errorf("error building calendar client %w", err)
	// }

	// build pdf client
	pc, err := pdf.NewPdfClient()
	if err != nil {
		return fmt.Errorf("error starting pdf client %w", err)
	}

	parsingClient := parser.NewBookingAgentParser(appConfig.ParserBaseUrl)

	bookingService, err := booking.NewService(bookingStore, parsingClient, pc)
	if err != nil {
		return fmt.Errorf("error creating booking service: %w", err)
	}

	// build authentication service
	as, err := auth.NewService(
		appConfig.SessionSecret,
		appConfig.Admin,
		appConfig.AdminSecret,
		appConfig.ApiKey,
	)
	if err != nil {
		return fmt.Errorf("error starting auth service %w", err)
	}

	port := appConfig.Port

	origins := appConfig.Origins

	srv, err := server.New(
		bookingService,
		as,
		config.NewHost(), // TODO: move to the database at some point
		server.WithPort(port),
		server.WithFileSystem(assets.Static),
		server.WithDebug(appConfig.Debug),
		server.WithSecretKey(appConfig.SecretKey),
		server.WithOrigins(origins),
	)
	if err != nil {
		return fmt.Errorf("error starting server %w", err)
	}

	srv.Start(ctx)
	return nil
}
