package cmd import ( "encoding/json" "fmt" "github.com/frenocorp/pop/internal/contact" "github.com/spf13/cobra" ) func contactCmd() *cobra.Command { cmd := &cobra.Command{ Use: "contact", Short: "Manage contacts", Long: `List, add, edit, and delete contacts.`, } cmd.AddCommand(contactListCmd()) cmd.AddCommand(contactAddCmd()) cmd.AddCommand(contactEditCmd()) cmd.AddCommand(contactDeleteCmd()) return cmd } func contactListCmd() *cobra.Command { cmd := &cobra.Command{ Use: "list", Short: "List all contacts", RunE: func(cmd *cobra.Command, args []string) error { manager := contact.NewContactManager() page, _ := cmd.Flags().GetInt("page") pageSize, _ := cmd.Flags().GetInt("page-size") search, _ := cmd.Flags().GetString("search") req := contact.ListContactsRequest{ Page: page, PageSize: pageSize, Search: search, } resp, err := manager.List(req) if err != nil { return fmt.Errorf("failed to list contacts: %w", err) } if len(resp.Contacts) == 0 { fmt.Println("No contacts found") return nil } data, _ := json.MarshalIndent(resp.Contacts, "", " ") fmt.Println(string(data)) return nil }, } cmd.Flags().IntP("page", "p", 0, "Page number") cmd.Flags().IntP("page-size", "n", 10, "Items per page") cmd.Flags().StringP("search", "s", "", "Search by email or name") return cmd } func contactAddCmd() *cobra.Command { cmd := &cobra.Command{ Use: "add", Short: "Add a new contact", RunE: func(cmd *cobra.Command, args []string) error { email, _ := cmd.Flags().GetString("email") name, _ := cmd.Flags().GetString("name") phone, _ := cmd.Flags().GetString("phone") if email == "" { return fmt.Errorf("email is required") } manager := contact.NewContactManager() req := contact.CreateContactRequest{ Email: email, Name: name, Phone: phone, } contact, err := manager.Create(req) if err != nil { return fmt.Errorf("failed to create contact: %w", err) } data, _ := json.MarshalIndent(contact, "", " ") fmt.Printf("Created contact:\n%s\n", string(data)) return nil }, } cmd.Flags().StringP("email", "e", "", "Contact email (required)") cmd.Flags().StringP("name", "n", "", "Contact name") cmd.Flags().StringP("phone", "p", "", "Contact phone") return cmd } func contactEditCmd() *cobra.Command { cmd := &cobra.Command{ Use: "edit ", Short: "Edit a contact", RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("contact ID is required") } id := args[0] manager := contact.NewContactManager() _, err := manager.Get(id) if err != nil { return fmt.Errorf("failed to get contact: %w", err) } name, _ := cmd.Flags().GetString("name") phone, _ := cmd.Flags().GetString("phone") address, _ := cmd.Flags().GetString("address") notes, _ := cmd.Flags().GetString("notes") req := contact.UpdateContactRequest{} // Only set pointer fields when the flag was explicitly changed if cmd.Flags().Changed("name") { req.Name = &name } if cmd.Flags().Changed("phone") { req.Phone = &phone } if cmd.Flags().Changed("address") { req.Address = &address } if cmd.Flags().Changed("notes") { req.Notes = ¬es } updated, err := manager.Update(id, req) if err != nil { return fmt.Errorf("failed to update contact: %w", err) } data, _ := json.MarshalIndent(updated, "", " ") fmt.Printf("Updated contact:\n%s\n", string(data)) return nil }, } cmd.Flags().StringP("name", "n", "", "New name") cmd.Flags().StringP("phone", "p", "", "New phone") cmd.Flags().StringP("address", "a", "", "New address") cmd.Flags().StringP("notes", "o", "", "New notes") return cmd } func contactDeleteCmd() *cobra.Command { cmd := &cobra.Command{ Use: "delete ", Short: "Delete a contact", RunE: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("contact ID is required") } id := args[0] manager := contact.NewContactManager() if err := manager.Delete(id); err != nil { return fmt.Errorf("failed to delete contact: %w", err) } fmt.Printf("Deleted contact: %s\n", id) return nil }, } return cmd }