#!/bin/bash
#
# Payload CMS Tenant Setup Script
# ================================
# Sets up tenants (porwoll.de, blogwoman.de) with all content
#
# Usage:
#   ./setup.sh [OPTIONS] <tenant>
#
# Options:
#   -e, --env        Environment: staging|production (default: staging)
#   -u, --user       Admin email
#   -p, --password   Admin password (or use PAYLOAD_PASSWORD env var)
#   -t, --tenant-id  Override tenant ID
#   -d, --dry-run    Show what would be created without making changes
#   -v, --verbose    Verbose output
#   -h, --help       Show this help
#
# Examples:
#   ./setup.sh porwoll                           # Setup porwoll.de on staging
#   ./setup.sh -e production blogwoman           # Setup blogwoman.de on production
#   ./setup.sh -e production -t 5 porwoll        # Setup with specific tenant ID
#   ./setup.sh --dry-run porwoll                 # Preview without changes

set -euo pipefail

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

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Defaults
ENV="staging"
DRY_RUN=false
VERBOSE=false
ADMIN_EMAIL=""
ADMIN_PASSWORD="${PAYLOAD_PASSWORD:-}"
TENANT_ID_OVERRIDE=""

# API URLs
declare -A API_URLS=(
    ["staging"]="https://pl.porwoll.tech/api"
    ["production"]="https://cms.c2sgmbh.de/api"
)

# Default Tenant IDs (can be overridden)
declare -A DEFAULT_TENANT_IDS=(
    ["porwoll"]="4"
    ["blogwoman"]="6"
)

# State
TOKEN=""
CREATED_PAGE_IDS=()
declare -A PAGE_ID_MAP

#######################################
# Logging functions
#######################################
log() { echo -e "${BLUE}[INFO]${NC} $*"; }
success() { echo -e "${GREEN}[OK]${NC} $*"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
debug() { [[ "$VERBOSE" == "true" ]] && echo -e "[DEBUG] $*" || true; }

#######################################
# Print usage
#######################################
usage() {
    cat << 'EOF'
Payload CMS Tenant Setup Script
================================
Sets up tenants (porwoll.de, blogwoman.de) with all content

Usage:
  ./setup.sh [OPTIONS] <tenant>

Options:
  -e, --env        Environment: staging|production (default: staging)
  -u, --user       Admin email
  -p, --password   Admin password (or use PAYLOAD_PASSWORD env var)
  -t, --tenant-id  Override tenant ID
  -d, --dry-run    Show what would be created without making changes
  -v, --verbose    Verbose output
  -h, --help       Show this help

Examples:
  ./setup.sh porwoll                           # Setup porwoll.de on staging
  ./setup.sh -e production blogwoman           # Setup blogwoman.de on production
  ./setup.sh -e production -t 5 porwoll        # Setup with specific tenant ID
  ./setup.sh --dry-run porwoll                 # Preview without changes
EOF
    exit 0
}

#######################################
# Parse command line arguments
#######################################
parse_args() {
    while [[ $# -gt 0 ]]; do
        case $1 in
            -e|--env)
                ENV="$2"
                shift 2
                ;;
            -u|--user)
                ADMIN_EMAIL="$2"
                shift 2
                ;;
            -p|--password)
                ADMIN_PASSWORD="$2"
                shift 2
                ;;
            -t|--tenant-id)
                TENANT_ID_OVERRIDE="$2"
                shift 2
                ;;
            -d|--dry-run)
                DRY_RUN=true
                shift
                ;;
            -v|--verbose)
                VERBOSE=true
                shift
                ;;
            -h|--help)
                usage
                ;;
            -*)
                error "Unknown option: $1"
                exit 1
                ;;
            *)
                TENANT="$1"
                shift
                ;;
        esac
    done

    # Validate
    if [[ -z "${TENANT:-}" ]]; then
        error "Tenant name required. Use: porwoll or blogwoman"
        exit 1
    fi

    if [[ ! -d "$SCRIPT_DIR/tenants/$TENANT" ]]; then
        error "Unknown tenant: $TENANT. Available: porwoll, blogwoman"
        exit 1
    fi

    if [[ ! "${API_URLS[$ENV]+isset}" ]]; then
        error "Unknown environment: $ENV. Use: staging or production"
        exit 1
    fi

    API_URL="${API_URLS[$ENV]}"
    TENANT_ID="${TENANT_ID_OVERRIDE:-${DEFAULT_TENANT_IDS[$TENANT]}}"
}

#######################################
# Prompt for credentials if needed
#######################################
get_credentials() {
    if [[ -z "$ADMIN_EMAIL" ]]; then
        read -p "Admin Email: " ADMIN_EMAIL
    fi
    if [[ -z "$ADMIN_PASSWORD" ]]; then
        read -sp "Admin Password: " ADMIN_PASSWORD
        echo
    fi
}

#######################################
# API Functions
#######################################

# Login and get JWT token
api_login() {
    log "Logging in to $API_URL..."

    local response
    response=$(curl -s -X POST "$API_URL/users/login" \
        -H "Content-Type: application/json" \
        -d "{\"email\": \"$ADMIN_EMAIL\", \"password\": \"$ADMIN_PASSWORD\"}" \
        -w '\n%{http_code}')

    local http_code
    http_code=$(echo "$response" | tail -1)
    local body
    body=$(echo "$response" | head -n -1)

    if [[ "$http_code" != "200" ]]; then
        error "Login failed (HTTP $http_code)"
        debug "$body"
        exit 1
    fi

    TOKEN=$(echo "$body" | jq -r '.token')
    if [[ -z "$TOKEN" || "$TOKEN" == "null" ]]; then
        error "Failed to extract token from response"
        exit 1
    fi

    success "Login successful"
}

# Generic API POST
api_post() {
    local endpoint="$1"
    local data="$2"
    local description="${3:-}"

    if [[ "$DRY_RUN" == "true" ]]; then
        log "[DRY-RUN] Would POST to $endpoint: $description"
        echo '{"doc":{"id":0}}'
        return 0
    fi

    local response
    response=$(curl -s -X POST "$API_URL/$endpoint" \
        -H "Authorization: JWT $TOKEN" \
        -H "Content-Type: application/json" \
        -d "$data" \
        -w '\n%{http_code}')

    local http_code
    http_code=$(echo "$response" | tail -1)
    local body
    body=$(echo "$response" | head -n -1)

    if [[ "$http_code" == "201" || "$http_code" == "200" ]]; then
        debug "POST $endpoint: HTTP $http_code"
        echo "$body"
    else
        warn "POST $endpoint failed (HTTP $http_code)"
        debug "$body"
        echo "$body"
        return 1
    fi
}

# Generic API PATCH
api_patch() {
    local endpoint="$1"
    local data="$2"

    if [[ "$DRY_RUN" == "true" ]]; then
        log "[DRY-RUN] Would PATCH $endpoint"
        return 0
    fi

    local response
    response=$(curl -s -X PATCH "$API_URL/$endpoint" \
        -H "Authorization: JWT $TOKEN" \
        -H "Content-Type: application/json" \
        -d "$data" \
        -w '\n%{http_code}')

    local http_code
    http_code=$(echo "$response" | tail -1)

    if [[ "$http_code" == "200" ]]; then
        debug "PATCH $endpoint: OK"
        return 0
    else
        warn "PATCH $endpoint failed (HTTP $http_code)"
        return 1
    fi
}

# Generic API GET
api_get() {
    local endpoint="$1"

    curl -s -G "$API_URL/$endpoint" \
        -H "Authorization: JWT $TOKEN"
}

# Check if documents exist for tenant
check_existing() {
    local collection="$1"
    local response
    local count

    response=$(api_get "$collection?where[tenant][equals]=$TENANT_ID&limit=1")
    debug "check_existing response: $response"

    # Handle API errors or invalid JSON
    if ! count=$(echo "$response" | jq -e '.totalDocs // 0' 2>/dev/null); then
        warn "Failed to check existing $collection (API error or invalid response)"
        debug "Response was: $response"
        echo "0"
        return 0
    fi

    echo "$count"
}

#######################################
# Create Site Settings
#######################################
create_site_settings() {
    log "Creating Site Settings..."

    local config_file="$SCRIPT_DIR/tenants/$TENANT/site-settings.json"
    if [[ ! -f "$config_file" ]]; then
        warn "No site-settings.json found for $TENANT"
        return
    fi

    # Check if exists
    local existing
    existing=$(check_existing "site-settings")

    local data
    data=$(cat "$config_file" | jq --argjson tid "$TENANT_ID" '.tenant = $tid')

    if [[ "$existing" -gt 0 ]]; then
        log "Site Settings already exists, updating..."
        local id
        id=$(api_get "site-settings?where[tenant][equals]=$TENANT_ID&limit=1" | jq -r '.docs[0].id')
        api_patch "site-settings/$id" "$data"
    else
        api_post "site-settings" "$data" "Site Settings"
    fi

    success "Site Settings configured"
}

#######################################
# Create Social Links
#######################################
create_social_links() {
    log "Creating Social Links..."

    local config_file="$SCRIPT_DIR/tenants/$TENANT/social-links.json"
    if [[ ! -f "$config_file" ]]; then
        warn "No social-links.json found for $TENANT"
        return 0
    fi

    # Check existing
    local existing
    existing=$(check_existing "social-links") || existing=0

    if [[ "$existing" -gt 0 ]]; then
        warn "Social Links already exist ($existing found), skipping..."
        return 0
    fi

    local count=0
    local failed=0
    local link
    local links
    links=$(jq -c '.[]' "$config_file" 2>/dev/null) || {
        warn "Failed to parse social-links.json"
        return 0
    }

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

        local data
        data=$(echo "$link" | jq --argjson tid "$TENANT_ID" '. + {tenant: $tid}') || continue
        local platform
        platform=$(echo "$link" | jq -r '.platform') || platform="unknown"

        debug "Creating social link: $platform"
        if api_post "social-links" "$data" "$platform" > /dev/null 2>&1; then
            count=$((count + 1))
        else
            failed=$((failed + 1))
            warn "Failed to create social link: $platform"
        fi
    done <<< "$links"

    if [[ "$failed" -gt 0 ]]; then
        warn "Created $count Social Links ($failed failed)"
    else
        success "Created $count Social Links"
    fi
}

#######################################
# Create Pages
#######################################
create_pages() {
    log "Creating Pages..."

    local config_file="$SCRIPT_DIR/tenants/$TENANT/pages.json"
    if [[ ! -f "$config_file" ]]; then
        warn "No pages.json found for $TENANT"
        return 0
    fi

    local count=0
    local skipped=0
    local failed=0
    local pages
    pages=$(jq -c '.[]' "$config_file" 2>/dev/null) || {
        warn "Failed to parse pages.json"
        return 0
    }

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

        local slug title
        slug=$(echo "$page" | jq -r '.slug' 2>/dev/null) || continue
        title=$(echo "$page" | jq -r '.title' 2>/dev/null) || title="$slug"

        # Check if page exists
        local response existing
        response=$(api_get "pages?where[tenant][equals]=$TENANT_ID&where[slug][equals]=$slug&limit=1") || response="{}"
        existing=$(echo "$response" | jq '.totalDocs // 0' 2>/dev/null) || existing=0

        if [[ "$existing" -gt 0 ]]; then
            debug "Page '$slug' already exists, skipping..."
            local id
            id=$(echo "$response" | jq -r '.docs[0].id' 2>/dev/null) || id=""
            [[ -n "$id" && "$id" != "null" ]] && PAGE_ID_MAP["$slug"]="$id"
            skipped=$((skipped + 1))
            continue
        fi

        local data
        data=$(echo "$page" | jq --argjson tid "$TENANT_ID" '. + {tenant: $tid}') || continue

        local post_response
        if post_response=$(api_post "pages" "$data" "$title" 2>/dev/null); then
            local id
            id=$(echo "$post_response" | jq -r '.doc.id // .id // 0' 2>/dev/null) || id="0"
            if [[ "$id" != "0" && "$id" != "null" ]]; then
                PAGE_ID_MAP["$slug"]="$id"
                count=$((count + 1))
                debug "Created page: $title (ID: $id)"
            else
                failed=$((failed + 1))
            fi
        else
            failed=$((failed + 1))
            warn "Failed to create page: $title"
        fi
    done <<< "$pages"

    if [[ "$failed" -gt 0 ]]; then
        warn "Created $count Pages ($skipped skipped, $failed failed)"
    else
        success "Created $count Pages ($skipped already existed)"
    fi

    # Show page ID mapping
    if [[ "$VERBOSE" == "true" ]]; then
        log "Page ID Mapping:"
        for slug in "${!PAGE_ID_MAP[@]}"; do
            echo "  $slug: ${PAGE_ID_MAP[$slug]}"
        done
    fi
}

#######################################
# Create Navigation
#######################################
create_navigation() {
    log "Creating Navigation..."

    local config_file="$SCRIPT_DIR/tenants/$TENANT/navigation.json"
    if [[ ! -f "$config_file" ]]; then
        warn "No navigation.json found for $TENANT"
        return 0
    fi

    # Check existing
    local existing
    existing=$(check_existing "navigations") || existing=0

    if [[ "$existing" -gt 0 ]]; then
        warn "Navigation already exists, skipping..."
        return 0
    fi

    # Read navigation template and replace page slugs with IDs
    local nav_data
    nav_data=$(cat "$config_file") || {
        warn "Failed to read navigation.json"
        return 0
    }

    # Replace placeholders with actual page IDs
    for slug in "${!PAGE_ID_MAP[@]}"; do
        local id="${PAGE_ID_MAP[$slug]}"
        nav_data=$(echo "$nav_data" | sed "s/\"PAGE_ID_${slug^^}\"/\"$id\"/g" | sed "s/\"PAGE_ID_$slug\"/$id/g") || true
    done

    # Add tenant ID
    nav_data=$(echo "$nav_data" | jq --argjson tid "$TENANT_ID" '. + {tenant: $tid}' 2>/dev/null) || {
        warn "Failed to add tenant ID to navigation data"
        return 0
    }

    if api_post "navigations" "$nav_data" "Navigation" > /dev/null 2>&1; then
        success "Navigation created"
    else
        warn "Failed to create navigation"
    fi
}

#######################################
# Verification
#######################################
verify_setup() {
    log "Verifying setup..."

    echo ""
    echo "=== Verification Report for $TENANT (Tenant ID: $TENANT_ID) ==="
    echo ""

    # Site Settings
    local ss_count
    ss_count=$(check_existing "site-settings")
    echo "Site Settings: $ss_count"

    # Social Links
    local sl_count
    sl_count=$(check_existing "social-links")
    echo "Social Links: $sl_count"

    # Pages
    local pages_count
    pages_count=$(check_existing "pages")
    echo "Pages: $pages_count"

    # List pages
    if [[ "$VERBOSE" == "true" ]]; then
        echo ""
        echo "Pages:"
        api_get "pages?where[tenant][equals]=$TENANT_ID&limit=50" | jq -r '.docs[] | "  [\(.id)] \(.title) (/\(.slug))"'
    fi

    # Navigation
    local nav_count
    nav_count=$(check_existing "navigations")
    echo "Navigation: $nav_count"

    echo ""
    echo "=== Setup Complete ==="
}

#######################################
# Main
#######################################
main() {
    parse_args "$@"

    echo ""
    echo "=================================="
    echo " Payload CMS Tenant Setup"
    echo "=================================="
    echo ""
    echo "Tenant:      $TENANT"
    echo "Tenant ID:   $TENANT_ID"
    echo "Environment: $ENV"
    echo "API URL:     $API_URL"
    echo "Dry Run:     $DRY_RUN"
    echo ""

    if [[ "$DRY_RUN" == "true" ]]; then
        warn "DRY RUN MODE - No changes will be made"
        echo ""
    fi

    get_credentials
    api_login

    echo ""
    log "Starting setup for $TENANT..."
    echo ""

    create_site_settings
    create_social_links
    create_pages
    create_navigation

    echo ""
    verify_setup
}

main "$@"
