#!/bin/bash

# CSV file structure:
# EMAIL_ACCOUNT EMAIL_PASSWORD_SRC EMAIL_HOST_SRC EMAIL_TYPE EMAIL_ADDRESS EMAIL_ALIAS EMAIL_FORWARD
# EMAIL_ACCOUNT: Name of the old email account on the source server. i.e. wp1234567-mm
# EMAIL_PASSWORD_SRC: Password for the email account on the source server
# EMAIL_HOST_SRC: Hostname of the source server. i.e.  wp1234567.server-he.de
# EMAIL_TYPE: can be mailbox or forward. Use mailbox to store mails on the server. Use forward for forward only mail accounts 
# EMAIL_ADDRESS: Primary email address for the account on the destination server. Must be unique and the domain must exist on the destination server
# EMAIL_ALIAS: Optional. Adds aliases to the email account. Please only provide the local part of the address and seperate multiple aliases with a ','
# EMAIL_FORWARD: Adds forwards to the email account. Seperate multiple aliases with a ','
# Delimiter is "€", since all other characters might be used in the passwords.
# Upper case letters may only be used in passwords

# Check if the necessary argument is provided
if [[ "$#" -lt 1 ]]; then
    echo "Usage: $0 -f <path_to_csv_file>"
    exit 1
fi

# Parse arguments
while getopts "f:" opt; do
    case $opt in
        f) CSV_FILE="$OPTARG" ;;
        *)
            echo "Invalid option: -$OPTARG"
            exit 1
            ;;
    esac
done

# Ensure the CSV file exists
if [[ ! -f "$CSV_FILE" ]]; then
    echo "Error: CSV file not found at $CSV_FILE"
    exit 1
fi

# Function to generate random password
GENERATE_PASSWORD() {
  tr -dc A-Za-z0-9 </dev/urandom | head -c 12
}

# Arrays for summary
SUCCESSFUL=()
FAILED=()

# Read CSV and process each line
HEADER_PROCESSED=false
while IFS='€' read -r EMAIL_ACCOUNT EMAIL_PASSWORD_SRC EMAIL_HOST_SRC EMAIL_TYPE EMAIL_ADDRESS EMAIL_ALIAS EMAIL_FORWARD; do
    # Skip empty lines
    if [[ -z "$EMAIL_ACCOUNT" || -z "$EMAIL_TYPE" || -z "$EMAIL_ADDRESS" ]]; then
        continue
    fi

    # Skip the header line if it exists
    if [[ "$HEADER_PROCESSED" == false ]]; then
        if [[ "$EMAIL_ACCOUNT" == "EMAIL_ACCOUNT" && "$EMAIL_PASSWORD_SRC" == "EMAIL_PASSWORD_SRC" && "$EMAIL_HOST_SRC" == "EMAIL_HOST_SRC" && "$EMAIL_TYPE" == "EMAIL_TYPE" && "$EMAIL_ADDRESS" == "EMAIL_ADDRESS" && "$EMAIL_ALIAS" == "EMAIL_ALIAS" && "$EMAIL_FORWARD" == "EMAIL_FORWARD" ]]; then
            HEADER_PROCESSED=true
            continue
        fi
        HEADER_PROCESSED=true
    fi

    # Determine action based on domain type
    case "$EMAIL_TYPE" in
      mailbox)

      # Validate email format
      if [[ ! "$EMAIL_ADDRESS" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
        FAILED+=("$EMAIL_ADDRESS (Invalid email format)")
        continue
      fi

      # Extract domain from email
      EMAIL_DOMAIN="${EMAIL_ADDRESS##*@}"
    
      # Check if domain exists in Plesk
      if ! plesk bin domain --info "$EMAIL_DOMAIN" &>/dev/null; then
        FAILED+=("$EMAIL_ADDRESS (Domain does not exist)")
        continue
      fi

      # Check if email account already exists
      if plesk bin mail --info "$EMAIL_ADDRESS" &>/dev/null; then
        FAILED+=("$EMAIL_ADDRESS (Email already exists)")
        continue
      fi
    
      # Generate random password if not provided
      EMAIL_PASSWORD_DST=$(GENERATE_PASSWORD)

    
      # Create email account
      if plesk bin mail --create "$EMAIL_ADDRESS" -passwd "$EMAIL_PASSWORD_DST" -mailbox true &>/dev/null; then
        SUCCESSFUL+=("$EMAIL_ADDRESS")
        
        # Write EMAIL_ACCOUNT EMAIL_PASSWORD_SRC EMAIL_HOST_SRC EMAIL_ADDRESS EMAIL_PASSWORD_DST EMAIL_HOST_DST to new file for mail-import
        # create dir, if not exist 
        mkdir -p /tmp/migration_csv

        # Extract wpID from EMAIL_HOST_SRC
        WPID=$(echo "$EMAIL_HOST_SRC" | awk -F'[.server]' '{print $1}')

        # Set EMAIL_HOST_DST to local servers hostname
        EMAIL_HOST_DST=$(uname -n)
      
        # Generate file name
        EMAIL_IMPORT=/tmp/migration_csv/email_import_"$WPID".csv

        # Create file with header, if not exist. Separator is space
        if [[ ! -f "$EMAIL_IMPORT" ]]; then
        echo "EMAIL_ACCOUNT EMAIL_PASSWORD_SRC EMAIL_HOST_SRC EMAIL_ADDRESS EMAIL_PASSWORD_DST EMAIL_HOST_DST" >> "$EMAIL_IMPORT"
        fi

        # Append current line to the file
        echo "$EMAIL_ACCOUNT $EMAIL_PASSWORD_SRC $EMAIL_HOST_SRC $EMAIL_ADDRESS $EMAIL_PASSWORD_DST $EMAIL_HOST_DST" >> "$EMAIL_IMPORT" 
      else
        FAILED+=("$EMAIL_ADDRESS (Creation failed)")
      fi

      # If $EMAIL_ALIAS is not empty, add them to the email address 
      if [[ -n "$EMAIL_ALIAS" ]]; then
        if plesk bin mail -u "$EMAIL_ADDRESS" -aliases add:"$EMAIL_ALIAS" 2> /dev/null; then
          SUCCESSFUL+=("$EMAIL_ADDRESS -> $EMAIL_ALIAS (Success)")
        else
          # Rollback in case of error
          plesk bin mail -u "$EMAIL_ADDRESS" -aliases del:"$EMAIL_ALIAS" 2> /dev/null
          FAILED+=("$EMAIL_ADDRESS -> $EMAIL_ALIAS (Failed to create alias)")
        fi
      fi

      # If $EMAIL_FORWARD is not empty, enable email forwarding for the email address add the forwards to the email address 
      if [[ -n "$EMAIL_FORWARD" ]]; then
        plesk bin mail -u "$EMAIL_ADDRESS" -forwarding true -forwarding-addresses add:"$EMAIL_FORWARD"
        if [ $? -eq 0 ]; then
          echo "Successfully added forwarding for $EMAIL_ADDRESS -> $EMAIL_FORWARD."
          SUCCESSFUL+=("$EMAIL_ADDRESS -> $EMAIL_FORWARD")
        else
          echo "Failed to add forwarding for $EMAIL_ADDRESS -> $EMAIL_FORWARD."
          FAILED+=("$EMAIL_ADDRESS -> $EMAIL_FORWARD")
        fi
      fi
      ;;
      
    forward)
      # Extract domain from email
      EMAIL_DOMAIN="${EMAIL_ADDRESS##*@}"
    
      # Check if domain exists in Plesk
      if ! plesk bin domain --info "$EMAIL_DOMAIN" &>/dev/null; then
        FAILED+=("$EMAIL_ADDRESS (Domain does not exist)")
        continue
      fi

      # Check if the email account exists in Plesk
      EMAIL_EXISTS=$(plesk bin mail --info "$EMAIL_ADDRESS" 2>/dev/null)
      if [ -z "$EMAIL_EXISTS" ]; then
      
        # Create email account with forward if the account doesn't exist
        plesk bin mail --create "$EMAIL_ADDRESS" -mailbox false -forwarding true forwarding-addresses add:"$EMAIL_FORWARD"
        if [ $? -eq 0 ]; then
          echo "Created email forward for $EMAIL -> $EMAIL_FORWARD"
          SUCCESSFUL+=("$EMAIL_ADDRESS -> $EMAIL_FORWARD")
        else
          echo "Failed to create email forward for $EMAIL_ADDRESS"
          FAILED+=("$EMAIL_ADDRESS -> $EMAIL_FORWARD (Failed to create forward)")
        fi
      else
        # Add forward to existing email account
        plesk bin mail --update "$EMAIL_ADDRESS" -forwarding true forwarding-addresses add:"$EMAIL_FORWARD"
        if [ $? -eq 0 ]; then
          echo "Added forward for $EMAIL_ADDRESS -> $EMAIL_FORWARD"
          SUCCESSFUL+=("$EMAIL_ADDRESS -> $EMAIL_FORWARD")
        else
          echo "Failed to add forward for $EMAIL_ADDRESS"
          FAILED+=("$EMAIL_ADDRESS -> $EMAIL_FORWARD (Failed to add forward)")
        fi
      fi
      ;;

    *)
      echo "Unknown or unsupported email type $EMAIL_TYPE for $EMAIL_ADDRESS" && \
      FAILED+=("Unknown email type $EMAIL_TYPE for $EMAIL_ADDRESS.")
      ;;
  esac

done < <(tail -n +1 "$CSV_FILE")

# Print summary
echo "Summary:"
echo "---------"
echo "Successfully created entries:"
for ITEM in "${SUCCESSFUL[@]}"; do
  echo "  - $ITEM"
done
echo "---------"
echo "Failed to create entries:"
for ITEM in "${FAILED[@]}"; do
  echo "  - $ITEM"
done
echo "---------"