package main import ( "context" "log" "os" "os/signal" "syscall" tea "github.com/charmbracelet/bubbletea" "github.com/your-username/todo/src/ai" "github.com/your-username/todo/src/config" "github.com/your-username/todo/src/database" "github.com/your-username/todo/src/ui" ) func main() { // Setup logging logFile, err := os.OpenFile("todo.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { log.Fatal(err) } defer logFile.Close() log.SetOutput(logFile) // Create context that can be cancelled on signal ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Handle shutdown signals sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) go func() { <-sigChan cancel() }() // Load configuration cfg, err := config.LoadConfig() if err != nil { log.Fatalf("Failed to load config: %v", err) } // Initialize database db, err := database.NewDatabase(cfg.Database) if err != nil { log.Fatalf("Failed to initialize database: %v", err) } defer db.Close() // Initialize AI service aiService := ai.NewAIService(&cfg.AI) // Start background analyzer if enabled if cfg.UI.IdleStartHour >= 0 { analyzer := ai.NewBackgroundAnalyzer(db, aiService, cfg) go analyzer.Start(ctx) } // Initialize and start UI if err := tea.NewProgram(ui.New(db, aiService)).Start(); err != nil { log.Printf("Error running program: %v", err) os.Exit(1) } }