#!/bin/bash
set -euo pipefail

# Template Validation Script
# Validates all rdev templates by:
#   1. Creating a test project
#   2. Adding each component type
#   3. Verifying files exist and compile
#   4. Running CI pipeline
#   5. Cleaning up
#
# Usage: ./cookbooks/scripts/template-validation.sh <command>
# Commands: run, quick, cleanup

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Parse --auto-teardown flag from args
ARGS=("$@")
for i in "${!ARGS[@]}"; do
    if [[ "${ARGS[$i]}" == "--auto-teardown" ]]; then
        AUTO_TEARDOWN="true"
        unset 'ARGS[$i]'
    fi
done
ARGS=("${ARGS[@]}")  # Re-index array

COMMAND="${ARGS[0]:-run}"
PROJECT_NAME="template-validation-$(date +%s)"

# Register cleanup trap for auto-teardown
register_cleanup_trap

# Component types to test
COMPONENT_TYPES=(
    "service"
    "worker"
    "app-astro"
    "app-react"
    "app-nextjs"
    "cli"
)

print_banner() {
    echo ""
    echo -e "${BLUE}╔══════════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${BLUE}║       rdev Template Validation - Full Integration Test           ║${NC}"
    echo -e "${BLUE}╚══════════════════════════════════════════════════════════════════╝${NC}"
    echo ""
}

validate_template_compilation() {
    local project_id="$1"
    local git_owner
    git_owner=$(get_git_owner)

    print_header "Validating Template Compilation"

    local failures=0

    # Check each key file exists
    echo "Checking skeleton files..."

    local files_to_check=(
        "CLAUDE.md"
        "README.md"
        "go.work"
        "pnpm-workspace.yaml"
        ".woodpecker.yml"
        ".golangci.yml"
        "docker-compose.yml"
        "pkg/README.md"
        "scripts/dev.sh"
        "scripts/discover.sh"
        "scripts/quality.sh"
        "scripts/install.sh"
    )

    for file in "${files_to_check[@]}"; do
        local check
        check=$(curl -s -o /dev/null -w "%{http_code}" \
            "https://git.threesix.ai/api/v1/repos/$git_owner/$project_id/contents/$file" \
            -H "Authorization: token ${GITEA_TOKEN:-}" 2>/dev/null)

        if [[ "$check" == "200" ]]; then
            print_success "$file"
        else
            print_error "$file (HTTP $check)"
            ((failures++))
        fi
    done

    # Check pkg/ packages
    echo ""
    echo "Checking pkg/ packages..."

    local pkg_dirs=(
        "pkg/app"
        "pkg/httperror"
        "pkg/httpresponse"
        "pkg/httpvalidation"
        "pkg/middleware"
        "pkg/auth"
    )

    for pkg_dir in "${pkg_dirs[@]}"; do
        local check
        check=$(curl -s "https://git.threesix.ai/api/v1/repos/$git_owner/$project_id/contents/$pkg_dir" \
            -H "Authorization: token ${GITEA_TOKEN:-}" 2>/dev/null | jq -r 'if type == "array" then "ok" else "not found" end')

        if [[ "$check" == "ok" ]]; then
            print_success "$pkg_dir/"
        else
            print_warning "$pkg_dir/ (may be optional)"
        fi
    done

    # Check packages/
    echo ""
    echo "Checking packages/..."

    local packages=(
        "packages/ui"
        "packages/layout"
        "packages/auth"
        "packages/logger"
        "packages/api-client"
    )

    for pkg in "${packages[@]}"; do
        local check
        check=$(curl -s "https://git.threesix.ai/api/v1/repos/$git_owner/$project_id/contents/$pkg/package.json" \
            -H "Authorization: token ${GITEA_TOKEN:-}" 2>/dev/null | jq -r '.name // "not found"')

        if [[ "$check" == "package.json" ]]; then
            print_success "$pkg/"
        else
            print_warning "$pkg/ (may be optional)"
        fi
    done

    echo ""
    if [[ $failures -gt 0 ]]; then
        print_error "Template compilation validation: $failures failures"
        return 1
    else
        print_success "Template compilation validation: all required files present"
        return 0
    fi
}

validate_component() {
    local project_id="$1"
    local comp_type="$2"
    local comp_name="$3"
    local git_owner
    git_owner=$(get_git_owner)

    echo ""
    echo "Validating $comp_type component..."

    # Determine expected directory
    local comp_dir
    case "$comp_type" in
        service)
            comp_dir="services/$comp_name"
            ;;
        worker)
            comp_dir="workers/$comp_name"
            ;;
        app-astro|app-react|app-nextjs)
            comp_dir="apps/$comp_name"
            ;;
        cli)
            comp_dir="cli/$comp_name"
            ;;
    esac

    # Check component directory exists
    local check
    check=$(curl -s "https://git.threesix.ai/api/v1/repos/$git_owner/$project_id/contents/$comp_dir" \
        -H "Authorization: token ${GITEA_TOKEN:-}" 2>/dev/null | jq -r 'if type == "array" then "ok" else "not found" end')

    if [[ "$check" == "ok" ]]; then
        print_success "$comp_type: $comp_dir/ exists"
    else
        print_error "$comp_type: $comp_dir/ not found"
        return 1
    fi

    # Check component.yaml exists
    local yaml_check
    yaml_check=$(curl -s -o /dev/null -w "%{http_code}" \
        "https://git.threesix.ai/api/v1/repos/$git_owner/$project_id/contents/$comp_dir/component.yaml" \
        -H "Authorization: token ${GITEA_TOKEN:-}" 2>/dev/null)

    if [[ "$yaml_check" == "200" ]]; then
        print_success "$comp_type: component.yaml exists"
    else
        print_warning "$comp_type: component.yaml not found"
    fi

    # Check Dockerfile exists
    local docker_check
    docker_check=$(curl -s -o /dev/null -w "%{http_code}" \
        "https://git.threesix.ai/api/v1/repos/$git_owner/$project_id/contents/$comp_dir/Dockerfile" \
        -H "Authorization: token ${GITEA_TOKEN:-}" 2>/dev/null)

    if [[ "$docker_check" == "200" ]]; then
        print_success "$comp_type: Dockerfile exists"
    else
        print_warning "$comp_type: Dockerfile not found (may be optional)"
    fi

    return 0
}

add_component() {
    local comp_type="$1"
    local comp_name="$2"

    echo "Adding $comp_type component: $comp_name"

    local payload
    payload=$(jq -n \
        --arg type "$comp_type" \
        --arg name "$comp_name" \
        '{type: $type, name: $name}')

    local result
    result=$(api_call POST "/projects/$PROJECT_NAME/components" "$payload")

    local path
    path=$(echo "$result" | jq -r '.data.path // .path // ""')

    if [[ -z "$path" ]]; then
        print_error "Failed to add $comp_type component"
        echo "$result" | jq '.'
        return 1
    fi

    print_success "Added $comp_type/$comp_name at $path"
    return 0
}

run_full_validation() {
    print_banner

    # Step 1: Create project
    print_header "Step 1: Creating Test Project"
    echo "Project name: $PROJECT_NAME"

    local create_payload
    create_payload=$(jq -n \
        --arg name "$PROJECT_NAME" \
        --arg desc "Template validation test project" \
        '{name: $name, description: $desc}')

    local create_result
    create_result=$(api_call POST "/project" "$create_payload")

    local domain
    domain=$(echo "$create_result" | jq -r '.data.domain // .domain // ""')

    if [[ -z "$domain" ]]; then
        print_error "Failed to create project"
        echo "$create_result" | jq '.'
        exit 1
    fi

    # Track project for auto-cleanup
    CLEANUP_PROJECT="$PROJECT_NAME"

    print_success "Project created with domain: $domain"

    # Step 2: Add all component types
    print_header "Step 2: Adding Components"

    local comp_names=()
    for comp_type in "${COMPONENT_TYPES[@]}"; do
        local comp_name
        case "$comp_type" in
            service)
                comp_name="api"
                ;;
            worker)
                comp_name="jobs"
                ;;
            app-astro)
                comp_name="landing"
                ;;
            app-react)
                comp_name="web"
                ;;
            app-nextjs)
                comp_name="dashboard"
                ;;
            cli)
                comp_name="ctl"
                ;;
        esac

        if add_component "$comp_type" "$comp_name"; then
            comp_names+=("$comp_type:$comp_name")
        fi
    done

    # Wait for git to sync
    print_header "Step 3: Waiting for Git Sync"
    echo "Waiting 15 seconds for git to propagate..."
    sleep 15

    # Step 4: Validate skeleton files
    print_header "Step 4: Validating Skeleton"
    validate_template_compilation "$PROJECT_NAME" || true

    # Step 5: Validate each component
    print_header "Step 5: Validating Components"
    for comp in "${comp_names[@]}"; do
        local type="${comp%%:*}"
        local name="${comp##*:}"
        validate_component "$PROJECT_NAME" "$type" "$name" || true
    done

    # Step 6: Check CI pipeline
    print_header "Step 6: Checking CI Pipeline"
    if wait_for_pipeline "$PROJECT_NAME" 60 5; then
        print_success "CI pipeline completed successfully"
    else
        print_warning "CI pipeline did not complete (may need investigation)"
    fi

    # Summary
    print_header "Validation Summary"
    echo "Project: $PROJECT_NAME"
    echo "Domain: https://$domain"
    echo "Git: https://git.threesix.ai/$(get_git_owner)/$PROJECT_NAME"
    echo "CI: https://ci.threesix.ai/$(get_git_owner)/$PROJECT_NAME"
    echo ""
    echo "Components tested:"
    for comp in "${comp_names[@]}"; do
        echo "  - $comp"
    done
    echo ""
    print_warning "Remember to clean up: $0 cleanup $PROJECT_NAME"
}

run_quick_validation() {
    print_banner
    echo "Quick validation: checking template API responses only"
    echo ""

    # Check skeleton template info
    print_header "Checking Skeleton Template"
    local skeleton_info
    skeleton_info=$(api_call GET "/templates/skeleton")
    echo "$skeleton_info" | jq '.data // .'

    # Check component templates
    print_header "Checking Component Templates"
    local comp_templates
    comp_templates=$(api_call GET "/templates/components")
    echo "$comp_templates" | jq '.data.components // .data // .'

    # Verify each component type exists
    print_header "Verifying Component Types"
    for comp_type in "${COMPONENT_TYPES[@]}"; do
        local info
        info=$(api_call GET "/templates/components/$comp_type" 2>/dev/null || echo '{}')
        local found
        found=$(echo "$info" | jq -r '.data.type // ""')

        if [[ "$found" == "$comp_type" ]]; then
            print_success "$comp_type template available"
        else
            print_error "$comp_type template not found"
        fi
    done
}

cleanup() {
    local project_to_delete="${2:-$PROJECT_NAME}"

    print_header "Cleaning Up: $project_to_delete"

    local result
    result=$(api_call DELETE "/project/$project_to_delete")
    echo "$result" | jq '.'

    print_success "Project deleted. Gitea repo preserved."
}

case "$COMMAND" in
    run)
        run_full_validation
        ;;
    quick)
        run_quick_validation
        ;;
    cleanup)
        cleanup "$@"
        ;;
    *)
        echo "Usage: $0 <command>"
        echo "Commands:"
        echo "  run      - Full validation (creates project, adds all components, checks CI)"
        echo "  quick    - Quick check (API responses only, no project creation)"
        echo "  cleanup  - Delete test project (optionally specify project name)"
        exit 1
        ;;
esac
