#!/usr/bin/env python3

import os
import subprocess
import logging
import shutil
from datetime import datetime

LOG_FILE = "/var/log/mspub_setup.log"
LOG_DIR = "/var/log"

def main():
	check_root()
	log_action("MSPUB Web Server Setup Script started.")
	system_updater()
	install_packages()
	configure_firewall()
	create_web_directory()
	create_sftp_directory()
	create_publishing_group()
	deploy_landing_page()
	configure_nginx_site()
	enable_services()
	verify_config()

	print("\nMSPUB Web Server Setup Complete!")
	log_action("MSPUB web server setup completed successfully.")

def log_action(message):
	"""Write script activity to the log file."""
	timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
	with open(LOG_FILE, "a") as log:
		log.write(f"[{timestamp}] {message}\n")

def run_command(command):
	"""Run a Linux command and log success or failure."""
	try:
		result = subprocess.run(
			command,
			shell=True,
			check=True,
			text=True,
			capture_output=True
			)
		log_action(f"SUCCESS: {command}")
		return result.stdout

	except subprocess.CalledProcessError as error:
		log_action(f"ERROR {command}")
		log_action(error.stderr)
		print(f"Command failed: {command}")
		print(error.stderr)
		exit(1)

def check_root():
	"""Verify the script is running with root privileges."""
	if os.geteuid() !=0:
		print("The MSPUB Webserver Setup script must be run with sudo privileges.")
		exit(1)

	log_action("Root privilege check passed.")

def system_updater():
	"""Update Ubuntu package repositories and installed packages."""
	print ("Updating system packages...")

	run_command("apt update")
	run_command("apt upgrade -y")

	log_action("System packages updated successfully.")

def install_packages():
	"""Install required packages for the MSPUB web server."""
	print("Installing required packages...")

	packages = [
		"nginx",
		"openssh-server",
		"ufw"
	]

	package_list = " ".join(packages)
	run_command(f"apt install {package_list} -y")

	log_action("Required packages installed successfully.")

def configure_firewall():
	"""Configuring UFW firewall rules."""
	print("Configuring firewall rules...")

	run_command("ufw allow OpenSSH")
	run_command("ufw allow 'Nginx Full'")
	run_command("ufw --force enable")

	log_action("Firewall configured sucessfully.")

def create_web_directory():
	"""Create the MSPUB web directory and set permissions."""
	print("Creating web directory...")

	web_dir = "/var/www/masterswordpub.net"

	run_command(f"mkdir -p {web_dir}")
	run_command(f"chown -R www-data:www-data {web_dir}")
	run_command(f"chmod -R 755 {web_dir}")

	log_action("Web directory created and permissions configured.")

def create_sftp_directory():
	"""Create SFTP directory structure for the Publishing department."""
	print("Creating SFTP directory...")

	sftp_dir = "/srv/sftp/publishing"

	run_command(f"mkdir -p {sftp_dir}")
	run_command(f"chmod 755 /srv/sftp")
	run_command(f"chmod 755 {sftp_dir}")

	log_action("SFTP directory structure created successfully.")

def create_publishing_group():
	"""Create the Publishing group for SFTP access."""
	print("Creating publishing group...")

	group_name = "publishing"

	group_exists = subprocess.run(
		f"getent group {group_name}",
		shell=True,
		text=True,
		capture_output=True
		)

	if group_exists.returncode == 0:
		log_action("Publishing group already exists.")
		print("Publishing group already exists.")
	else:
		run_command(f"groupadd {group_name}")
		log_action("Publishing group created successfully.")

def deploy_landing_page():
	"""Deploy a basic MSPUB internal website landing page."""
	print("Deploying MSPUB landing page...")

	source_file = "mspub_index.html"
	destination_file = "/var/www/masterswordpub.net/index.html"

	if not os.path.exists(source_file):
		log_action(f"ERROR: {source_file} not found.")
		print(f"Error: {source_file} not found. Please upload {source_file} to server.")
		exit(1)

	shutil.copy(source_file, destination_file)

	run_command(f'chown www-data:www-data {destination_file}')
	run_command(f"chmod 644 {destination_file}")

	log_action("MSPUB website deployed successfully.")

def configure_nginx_site():
	"""Configure Nginx to server the MSPUB website."""
	print("Configuring Nginx site...")

	site_config = "/etc/nginx/sites-available/masterswordpub.net"
	enabled_site = "/etc/nginx/sites-enabled/masterswordpub.net"
	default_site = "/etc/nginx/sites-enabled/default"

	nginx_config = """server {
	listen 80;
	listen [::]:80;

	server_name masterswordpub.net www.masterswordpub.net;

	root /var/www/masterswordpub.net;
	index index.html;

	location / {
		try_files $uri $uri/ =404;
		}
	}
	"""

	with open(site_config, "w") as file:
		file.write(nginx_config)

	if os.path.exists(default_site):
		run_command(f"rm {default_site}")

	if not os.path.exists(enabled_site):
		run_command(f"ln -s {site_config} {enabled_site}")

	run_command("nginx -t")
	run_command("systemctl reload nginx")

	log_action("Nginx site configured successfully.")

def enable_services():
	"""Enable and start required services."""
	print("Enabling and starting services...")

	services = [
		"nginx",
		"ssh"
	]

	for service in services:
		run_command(f"systemctl enable {service}")
		run_command(f"systemctl restart {service}")

	log_action("Required services enabled and started successfully.")

def verify_config():
	"""Verify web server configuration."""
	print("Verifying configuration...")

	checks = [
		("Nginx Service", "systemctl is-active nginx"),
		("SSH Service", "systemctl is-active ssh"),
		("Firewall Status", "ufw status"),
		("Website Directory", "test -d /var/www/masterswordpub.net"),
		("SFTP Directory", "test -d /srv/sftp/publishing"),
		("Publishing Group", "getent group publishing")
	]

	for check_name, command in checks:
		try:
			result = subprocess.run(
				command,
				shell=True,
				check=True,
				text=True,
				capture_output=True
			)

			log_action(f"VERIFIED: {check_name}")
			print(f"[PASS] {check_name}")

		except subprocess.CalledProcessError:
			log_action(f"FAILED: {check_name}")
			print(f"[FAIL] {check_name}")

	log_action("Configuration verification completed.")

if __name__ == "__main__":
	main()
