#!/bin/bash
# ============================================================
# Nexus Autoparts — Selective Backup (No TecDoc)
# Backs up schema + all data EXCEPT vehicle_parts fitments
# Includes all tenant databases
# ============================================================
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'

info()  { echo -e "${CYAN}[INFO]${NC}  $*"; }
ok()    { echo -e "${GREEN}[OK]${NC}    $*"; }
warn()  { echo -e "${YELLOW}[WARN]${NC}  $*"; }
err()   { echo -e "${RED}[ERROR]${NC} $*"; }
fatal() { err "$*"; exit 1; }

# ─── Configuration ─────────────────────────────────────────────────────────
BACKUP_DIR="${BACKUP_DIR:-${PROJECT_DIR}/backups}"
RETENTION_DAYS="${RETENTION_DAYS:-30}"
MASTER_DB="${MASTER_DB:-nexus_autoparts}"
DB_USER="${DB_USER:-nexus}"

# Load .env if exists
if [[ -f "${PROJECT_DIR}/.env" ]]; then
    set -a
    source "${PROJECT_DIR}/.env"
    set +a
fi

# Parse DB credentials from DATABASE_URL or MASTER_DB_URL
DB_URL="${MASTER_DB_URL:-${DATABASE_URL:-}}"
if [[ -n "$DB_URL" ]]; then
    # Extract components from postgresql://user:pass@host/dbname
    DB_HOST=$(echo "$DB_URL" | sed -n 's/.*@\([^:]*\).*/\1/p')
    DB_PORT=$(echo "$DB_URL" | sed -n 's/.*:\([0-9]*\)\/.*/\1/p')
    [[ -z "$DB_PORT" ]] && DB_PORT=5432
fi

TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="nexus_backup_${TIMESTAMP}"
BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}"

# ─── Pre-flight checks ─────────────────────────────────────────────────────
check_prerequisites() {
    info "Checking prerequisites..."

    if ! command -v pg_dump &>/dev/null; then
        fatal "pg_dump not found. Install: sudo apt install postgresql-client"
    fi

    if ! command -v pg_dumpall &>/dev/null; then
        fatal "pg_dumpall not found. Install: sudo apt install postgresql-client"
    fi

    # Test PostgreSQL connection
    if ! sudo -u postgres psql -c "SELECT 1" &>/dev/null; then
        fatal "Cannot connect to PostgreSQL. Is it running?"
    fi

    # Create backup directory
    mkdir -p "$BACKUP_PATH"

    ok "Prerequisites passed. Backup will be saved to: ${BACKUP_PATH}"
}

# ─── Backup master schema (structure only) ─────────────────────────────────
backup_master_schema() {
    info "Backing up master database schema (structure only)..."

    local output="${BACKUP_PATH}/01_master_schema.sql"

    sudo -u postgres pg_dump \
        --schema-only \
        --no-owner \
        --no-privileges \
        "$MASTER_DB" > "$output"

    local size=$(du -h "$output" | cut -f1)
    ok "Master schema: ${size}"
}

# ─── Backup master data (excluding vehicle_parts) ──────────────────────────
backup_master_data() {
    info "Backing up master database data (excluding vehicle_parts)..."

    local output="${BACKUP_PATH}/02_master_data.sql"
    local tables_file="${BACKUP_PATH}/_tables_to_backup.txt"

    # Get list of tables EXCEPT vehicle_parts
    sudo -u postgres psql "$MASTER_DB" -Atc "
        SELECT tablename FROM pg_tables
        WHERE schemaname = 'public'
        AND tablename != 'vehicle_parts'
        ORDER BY tablename;
    " > "$tables_file"

    local table_count=$(wc -l < "$tables_file")
    info "Found ${table_count} tables to backup (excluded: vehicle_parts)"

    # Build --table arguments
    local table_args=""
    while IFS= read -r table; do
        [[ -n "$table" ]] && table_args="$table_args --table=$table"
    done < "$tables_file"

    # Dump data only for selected tables
    sudo -u postgres pg_dump \
        --data-only \
        --no-owner \
        --no-privileges \
        $table_args \
        "$MASTER_DB" > "$output"

    # Compress
    gzip -f "$output"
    local size=$(du -h "${output}.gz" | cut -f1)
    ok "Master data (no TecDoc): ${size}"

    rm -f "$tables_file"
}

# ─── Backup vehicle_parts schema only ──────────────────────────────────────
backup_vehicle_parts_schema() {
    info "Backing up vehicle_parts schema only (structure, no data)..."

    local output="${BACKUP_PATH}/03_vehicle_parts_schema.sql"

    sudo -u postgres pg_dump \
        --schema-only \
        --no-owner \
        --no-privileges \
        --table=vehicle_parts \
        "$MASTER_DB" > "$output"

    local size=$(du -h "$output" | cut -f1)
    ok "vehicle_parts schema: ${size}"
}

# ─── Backup all tenant databases ───────────────────────────────────────────
backup_tenants() {
    info "Discovering tenant databases..."

    local tenants_file="${BACKUP_PATH}/_tenants.txt"

    sudo -u postgres psql "$MASTER_DB" -Atc "
        SELECT db_name FROM tenants WHERE is_active = true ORDER BY id;
    " > "$tenants_file"

    local tenant_count=$(wc -l < "$tenants_file")
    if [[ "$tenant_count" -eq 0 ]]; then
        warn "No active tenants found."
        rm -f "$tenants_file"
        return
    fi

    info "Found ${tenant_count} active tenant(s). Backing up..."

    while IFS= read -r db_name; do
        [[ -z "$db_name" ]] && continue

        # Sanitize filename
        local safe_name=$(echo "$db_name" | tr -cd 'a-z0-9_')
        local output="${BACKUP_PATH}/tenant_${safe_name}.sql"

        info "  → Backing up ${db_name}..."

        if sudo -u postgres psql -l | grep -q "^ ${db_name} "; then
            sudo -u postgres pg_dump \
                --no-owner \
                --no-privileges \
                "$db_name" > "$output"

            gzip -f "$output"
            local size=$(du -h "${output}.gz" | cut -f1)
            ok "  → ${db_name}: ${size}"
        else
            warn "  → ${db_name}: database not found, skipping"
        fi
    done < "$tenants_file"

    rm -f "$tenants_file"
}

# ─── Create manifest ───────────────────────────────────────────────────────
create_manifest() {
    local manifest="${BACKUP_PATH}/MANIFEST.txt"

    cat > "$manifest" << EOF
Nexus Autoparts — Selective Backup
Generated: $(date '+%Y-%m-%d %H:%M:%S')
Hostname: $(hostname)

CONTENTS:
---------
01_master_schema.sql         — Database structure (all tables, indexes, constraints)
02_master_data.sql.gz        — Data for all tables EXCEPT vehicle_parts
03_vehicle_parts_schema.sql  — Structure of vehicle_parts only (no data)
tenant_*.sql.gz              — Full backup of each active tenant database

RESTORE INSTRUCTIONS:
---------------------
1. Create empty database:
   createdb nexus_autoparts

2. Restore schema:
   psql nexus_autoparts < 01_master_schema.sql

3. Restore data:
   gunzip -c 02_master_data.sql.gz | psql nexus_autoparts

4. Restore vehicle_parts structure (empty):
   psql nexus_autoparts < 03_vehicle_parts_schema.sql

5. Restore tenants:
   createdb tenant_name
   gunzip -c tenant_name.sql.gz | psql tenant_name

RE-IMPORT TECDOC (optional):
----------------------------
To reload vehicle_parts data later:
   python3 scripts/import_tecdoc.py download
   python3 scripts/import_tecdoc.py import
EOF

    ok "Manifest created"
}

# ─── Compress final archive ────────────────────────────────────────────────
create_archive() {
    info "Creating final archive..."

    local archive="${BACKUP_DIR}/${BACKUP_NAME}.tar.gz"

    cd "$BACKUP_DIR"
    tar -czf "$archive" "$BACKUP_NAME"

    local archive_size=$(du -h "$archive" | cut -f1)
    local unpacked_size=$(du -sh "$BACKUP_PATH" | cut -f1)

    ok "Archive created: ${archive}"
    echo ""
    echo -e "  ${BOLD}Compressed:${NC}   ${archive_size}"
    echo -e "  ${BOLD}Unpacked:${NC}     ${unpacked_size}"
    echo ""

    # Remove temp directory (keep archive)
    rm -rf "$BACKUP_PATH"
}

# ─── Cleanup old backups ───────────────────────────────────────────────────
cleanup_old_backups() {
    info "Cleaning up backups older than ${RETENTION_DAYS} days..."

    local deleted=0
    while IFS= read -r file; do
        rm -f "$file"
        ((deleted++))
    done < <(find "$BACKUP_DIR" -name "nexus_backup_*.tar.gz" -mtime +$RETENTION_DAYS)

    if [[ "$deleted" -gt 0 ]]; then
        ok "Deleted ${deleted} old backup(s)"
    else
        info "No old backups to delete"
    fi
}

# ─── Main ──────────────────────────────────────────────────────────────────
main() {
    echo ""
    echo -e "${BOLD}${CYAN}"
    echo "  ========================================"
    echo "   Nexus Autoparts — Selective Backup"
    echo "  ========================================"
    echo -e "${NC}"
    echo ""

    check_prerequisites
    backup_master_schema
    backup_master_data
    backup_vehicle_parts_schema
    backup_tenants
    create_manifest
    create_archive
    cleanup_old_backups

    echo -e "${BOLD}${GREEN}"
    echo "  Backup completed successfully!"
    echo -e "${NC}"
    echo "  Location: ${BACKUP_DIR}/nexus_backup_${TIMESTAMP}.tar.gz"
    echo ""
}

main "$@"
