#!/usr/bin/env ruby
require 'etc'
require 'logger'
require 'optparse'
require 'redis'
require 'sisimai'
require 'json'

# Parse command-line arguments
options = {}
# options[:test] = true # Set the default mode to test
OptionParser.new do |opts|
  opts.banner = "Usage: bounce.rb [options]"

  opts.on("--test", "Run in test mode") do |v|
    options[:test] = true
  end

  opts.on("--prod", "Run in production mode") do |v|
    options[:test] = false
  end
end.parse!

# Configure Logger
# It should be with permission mail mail
logfile = '/var/mail/bounce_mail.txt'
error_logfile = '/var/mail/bounce_error.txt'

begin
  logger = Logger.new(logfile)
  error_logger = Logger.new(error_logfile)

  # Ensure log files are writable
  unless File.writable?(logfile)
    raise "Log file #{logfile} is not writable"
  end

  unless File.writable?(error_logfile)
    raise "Error log file #{error_logfile} is not writable"
  end

  logger.info("Script started") if options[:test]

  # Log the effective user ID and user name
  euid = Process.euid
  user = Etc.getpwuid(euid).name
  logger.info("Script started by user: #{user} (EUID: #{euid})") if options[:test]

  # Read mail from STDIN
  mail = STDIN.read
  logger.info("Mail read from STDIN: #{mail[0..100]}...") if options[:test] # Log the first 100 characters for debugging

  # Process mail with Sisimai
  v = Sisimai.rise(mail)
  logger.info("Sisimai processing completed") if options[:test]

  if v.is_a? Array
    begin
      redis = Redis.new(db: 5) # Connect to Redis only if there is a bounce

      v.each do |e|
        if options[:test]
          logger.info(e.to_json)
        else
          # Publish to Redis channel in production mode
          redis.publish('bounce_mail_channel', e.to_json)
        end
      end

    ensure
      # Ensure the Redis connection is closed
      redis.close if redis
      logger.info("Redis connection closed") if options[:test]
    end
  else
    logger.info('No bounce detected.') if options[:test]
  end

  logger.info("Script completed successfully") if options[:test]
  exit 0

rescue => e
  logger.error("An error occurred: #{e.message}") if options[:test]
  logger.error(e.backtrace.join("\n")) if options[:test]

  # Log error to error file
  error_logger.error("An error occurred: #{e.message}")
  error_logger.error(e.backtrace.join("\n"))

  exit 1
end
