package formatter import ( "fmt" "strings" "git.db.org.ai/dborg/internal/models" ) func FormatSkiptraceResults(resp interface{}, asJSON bool) (string, error) { var data map[string]interface{} switch r := resp.(type) { case *models.SkiptraceResponse: data = r.Data case *models.SkiptraceReportResponse: data = r.Data case *models.SkiptracePhoneResponse: data = r.Data case *models.SkiptraceEmailResponse: data = r.Data default: return "", fmt.Errorf("unsupported skiptrace response type") } err := PrintColorizedJSON(data) if err != nil { return "", fmt.Errorf("failed to marshal JSON: %w", err) } return "", nil } func formatSkiptraceData(sb *strings.Builder, data map[string]interface{}) { if person, ok := data["person"].(map[string]interface{}); ok { sb.WriteString(fmt.Sprintf("%s\n", Bold("Person Information:"))) formatPersonInfo(sb, person) delete(data, "person") } if phones, ok := data["phones"].([]interface{}); ok && len(phones) > 0 { sb.WriteString(fmt.Sprintf("\n%s\n", Bold("Phone Numbers:"))) for _, phone := range phones { if phoneMap, ok := phone.(map[string]interface{}); ok { if number, ok := phoneMap["number"].(string); ok { sb.WriteString(fmt.Sprintf(" %s %s", Dim("•"), Cyan(number))) if carrier, ok := phoneMap["carrier"].(string); ok && carrier != "" { sb.WriteString(fmt.Sprintf(" %s", Gray(fmt.Sprintf("(%s)", carrier)))) } if phoneType, ok := phoneMap["type"].(string); ok && phoneType != "" { sb.WriteString(fmt.Sprintf(" %s", Dim(phoneType))) } sb.WriteString("\n") } } } delete(data, "phones") } if emails, ok := data["emails"].([]interface{}); ok && len(emails) > 0 { sb.WriteString(fmt.Sprintf("\n%s\n", Bold("Email Addresses:"))) for _, email := range emails { if emailStr, ok := email.(string); ok { sb.WriteString(fmt.Sprintf(" %s %s\n", Dim("•"), Blue(emailStr))) } } delete(data, "emails") } if addresses, ok := data["addresses"].([]interface{}); ok && len(addresses) > 0 { sb.WriteString(fmt.Sprintf("\n%s\n", Bold("Addresses:"))) for _, addr := range addresses { if addrMap, ok := addr.(map[string]interface{}); ok { formatAddress(sb, addrMap) } } delete(data, "addresses") } if len(data) > 0 { sb.WriteString(fmt.Sprintf("\n%s\n", Bold("Additional Information:"))) if colorized, err := FormatColorizedJSON(data); err == nil { lines := strings.Split(colorized, "\n") for _, line := range lines { sb.WriteString(fmt.Sprintf(" %s\n", line)) } } } } func formatPersonInfo(sb *strings.Builder, person map[string]interface{}) { if name, ok := person["name"].(string); ok && name != "" { sb.WriteString(fmt.Sprintf(" %s %s\n", Cyan("Name:"), Bold(name))) } if age, ok := person["age"].(float64); ok && age > 0 { sb.WriteString(fmt.Sprintf(" %s %d\n", Cyan("Age:"), int(age))) } if dob, ok := person["dob"].(string); ok && dob != "" { sb.WriteString(fmt.Sprintf(" %s %s\n", Cyan("DOB:"), dob)) } } func formatAddress(sb *strings.Builder, addr map[string]interface{}) { var addrStr strings.Builder if street, ok := addr["street"].(string); ok && street != "" { addrStr.WriteString(street) } if city, ok := addr["city"].(string); ok && city != "" { if addrStr.Len() > 0 { addrStr.WriteString(", ") } addrStr.WriteString(city) } if state, ok := addr["state"].(string); ok && state != "" { if addrStr.Len() > 0 { addrStr.WriteString(", ") } addrStr.WriteString(state) } if zip, ok := addr["zip"].(string); ok && zip != "" { if addrStr.Len() > 0 { addrStr.WriteString(" ") } addrStr.WriteString(zip) } if addrStr.Len() > 0 { sb.WriteString(fmt.Sprintf(" %s %s\n", Dim("•"), addrStr.String())) } }