public with sharing class SlackOpportunityPublisher {

     
   // Production business channel
   // private static final String slackURL = 'https://hooks.slack.com/services/######'; 

   // Private channel for testing
   // private static final String slackURL = 'https://hooks.slack.com/services/#####'; 
     
    public class Oppty {
    
    
        @InvocableVariable(label='Opportunity Owner')
        public String opptyOwnerName;
        @InvocableVariable(label='Opportunity Items')
        public String opptyItems;
        @InvocableVariable(label='Account Name')
        public String acctName;
        @InvocableVariable(label='Account Industry')
        public String acctIndustry;
        @InvocableVariable(label='Amount')
        public Decimal amount;
     
     // Getting the monthly total
        AggregateResult[] monthlyInvoices = [SELECT SUM(SaaSOptics_Invoice_Amount__c)sum FROM SaaSOptics_Invoice__c WHERE SaaSOptics_Invoice_Date__c >= THIS_MONTH AND SaaSOptics_Invoice_Date__c <= TODAY ];
        public Decimal monthlySumAmount = (Decimal)monthlyInvoices[0].get('sum');
     
     // Getting the quaterly total
        AggregateResult[] quaterlyInvoices = [SELECT SUM(SaaSOptics_Invoice_Amount__c)sum FROM SaaSOptics_Invoice__c WHERE SaaSOptics_Invoice_Date__c >= THIS_QUARTER AND SaaSOptics_Invoice_Date__c < NEXT_QUARTER ];
        public Decimal quaterlySumAmount = (Decimal)quaterlyInvoices[0].get('sum');
     
     
     // Getting the annual total
        AggregateResult[] annualInvoices = [SELECT SUM(SaaSOptics_Invoice_Amount__c)sum FROM SaaSOptics_Invoice__c WHERE SaaSOptics_Invoice_Date__c >=2018-01-01 AND SaaSOptics_Invoice_Date__c <= TODAY ];
        public Decimal annualSumAmount = (Decimal)annualInvoices[0].get('sum');
        
        
    }  
     
    @InvocableMethod(label='Post to SlackV3')
    public static void postToSlack(List<Oppty> oppties) {   
        Oppty o = oppties[0]; // If bulk, only post first to avoid overloading Slack channel
        
        // Create a format that looks better in Slack when posted
        Map<String,Object> msg = new Map<String,Object>();
        List<String> args = new String[]{'0','number','###,###,##0.00'};
        
        // Formatting the amounts to have commas and decimal values
        String ot = String.format(o.amount.format(), args);
        String mt = String.format(o.monthlySumAmount.format(), args);
        String at = String.format(o.annualSumAmount.format(), args);
        String qt = String.format(o.quaterlySumAmount.format(), args);
        
        // Setting the message contents
        msg.put('text','Month total before order: $*' + mt + '*\n' + 'Quarter total before order: $*' + qt + '*\n' + 'Annual total before order: $*' + at + '*\n\n' + o.opptyOwnerName + ' just closed a new opportunity with *' + o.acctName + '* in the *' + o.acctIndustry + '* industry, worth a total of $*' + ot + '* . Check out the details in the document links below. :champagne:\n\n' + o.opptyItems);
        msg.put('mrkdwn', true);
        String body = JSON.serialize(msg);    
        System.enqueueJob(new QueueableSlackCall(slackURL, 'POST', body));
    }
     
    public class QueueableSlackCall implements System.Queueable, Database.AllowsCallouts {
         
        private final String url;
        private final String method;
        private final String body;
         
        public QueueableSlackCall(String url, String method, String body) {
            this.url = url;
            this.method = method;
            this.body = body;
        }
         
        public void execute(System.QueueableContext ctx) {
            HttpRequest req = new HttpRequest();
            req.setEndpoint(url);
            req.setMethod(method);
            req.setBody(body);
            Http http = new Http();
            if (!Test.isRunningTest()) { // HTTP callout is not allowed in tests apparently...
            HttpResponse res = http.send(req);
                }
 
        }
    }
}