from datetime import timedelta
from pathlib import Path

from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone

from ._dbutils import base_connection_args, encrypt_backup_file, pg_config, pg_env, require_binary, run_checked, sha256_file


class Command(BaseCommand):
    help = "Create a PostgreSQL custom-format backup, verify it, write SHA-256, and remove expired dumps."

    def add_arguments(self, parser):
        parser.add_argument("--prefix", default="hrpay")
        parser.add_argument("--no-retention", action="store_true")

    def handle(self, *args, **options):
        cfg = pg_config()
        pg_dump = require_binary("pg_dump")
        pg_restore = require_binary("pg_restore")
        backup_dir = Path(settings.BACKUP_DIR)
        backup_dir.mkdir(parents=True, exist_ok=True)

        stamp = timezone.localtime().strftime("%Y%m%d-%H%M%S")
        safe_prefix = "".join(c for c in options["prefix"] if c.isalnum() or c in "-_") or "hrpay"
        dump_path = backup_dir / f"{safe_prefix}-{stamp}.dump"

        cmd = [pg_dump, "--format=custom", "--no-owner", "--no-privileges", *base_connection_args(cfg), "--file", str(dump_path), str(cfg["NAME"])]
        run_checked(cmd, env=pg_env(cfg))

        # pg_restore --list parses the plaintext archive before encryption.
        run_checked([pg_restore, "--list", str(dump_path)], env=pg_env(cfg))
        backup_path = encrypt_backup_file(dump_path)
        digest = sha256_file(backup_path)
        digest_path = Path(str(backup_path) + ".sha256")
        digest_path.write_text(f"{digest}  {backup_path.name}\n")

        if not options["no_retention"]:
            cutoff = timezone.now() - timedelta(days=settings.BACKUP_RETENTION_DAYS)
            for old in list(backup_dir.glob("*.dump")) + list(backup_dir.glob("*.dump.enc")):
                try:
                    modified = timezone.datetime.fromtimestamp(old.stat().st_mtime, tz=timezone.get_current_timezone())
                    if modified < cutoff:
                        old.unlink(missing_ok=True)
                        Path(str(old) + ".sha256").unlink(missing_ok=True)
                except OSError:
                    pass

        self.stdout.write(self.style.SUCCESS(f"Backup created, protected and verified: {backup_path}"))
        self.stdout.write(f"SHA256: {digest}")
