package main

import (
	"context"
	"errors"
	"fmt"

	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/controller"
	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/infra/deps"
	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/infra/log"
	"github.com/tidbcloud/escalation-base/feishu_messager_v2/pkg/service"
)

func run(ctx context.Context, deps *deps.Deps) error {
	var err error
	exitCh := make(chan error)
	logger := log.Logger.WithName("Run")

	// run services
	logger.Info("start to run services")
	err = deps.Container.Invoke(func(m *service.Manager) error {
		go func() {
			err = m.RunServices()
			if err != nil {
				exitCh <- err
			}
		}()
		return nil
	})
	if err != nil {
		return fmt.Errorf("failed to run services: %s", err)
	}
	logger.Info("end to run services")

	// run api server
	logger.Info("start to run api server")
	err = deps.Container.Invoke(func(s *controller.APIServer) error {
		go func() {
			aerr := s.Run()
			if err != nil {
				exitCh <- aerr
			}
		}()
		return nil
	})
	if err != nil {
		return fmt.Errorf("failed to run api server: %s", err)
	}

	// block until shutdown or error
	exitErrs := []error{}
	select {
	case <-ctx.Done():
		err = nil
		log.Logger.Info("exit due to receiving a signal", "signal", context.Cause(ctx).Error())
	case err = <-exitCh:
		log.Logger.Error(err, "exit due to receiving an error")
		exitErrs = append(exitErrs, err)
	}

	// stop api server
	logger.Info("stopping api server")
	if err := deps.Container.Invoke(func(s *controller.APIServer) error {
		return s.Shutdown(ctx)
	}); err != nil {
		exitErrs = append(exitErrs, err)
	}
	logger.Info("stopped api server")

	// stop services
	logger.Info("stopping all services")
	if err := deps.Container.Invoke(func(m *service.Manager) {
		m.StopServices()
	}); err != nil {
		exitErrs = append(exitErrs, err)
	}
	logger.Info("stopped all services")

	// stop cron
	// logger.Info("stopping cron")
	// if err := deps.Container.Invoke(func(c *cron.Cron) {
	// 	c.Stop()
	// }); err != nil {
	// 	exitErrs = append(exitErrs, err)
	// }
	// logger.Info("stopped cron")

	return errors.Join(exitErrs...)
}
