#!/usr/bin/env nu

# Initialize OCI registry with required namespaces and policies

export def main [
    --registry-type: string = "zot"  # zot, harbor, distribution
    --registry-url: string = "localhost:5000"
    --admin-password: string = "admin"
    --skip-test
] {
    print "🚀 Initializing OCI registry..."
    print $"   Type: ($registry_type)"
    print $"   URL: ($registry_url)"

    # Wait for registry to be healthy
    print "\n⏳ Waiting for registry to be ready..."
    wait-for-registry-health $registry_url

    # Create namespaces
    print "\n📦 Creating namespaces..."
    create-default-namespaces $registry_url $registry_type $admin_password

    # Setup policies
    print "\n🔒 Configuring access policies..."
    setup-access-policies $registry_url $registry_type $admin_password

    # Push test image (unless skipped)
    if not $skip_test {
        print "\n🧪 Pushing test image..."
        push-test-image $registry_url $registry_type
    }

    print "\n✅ OCI registry initialized successfully!"
    print "\n📊 Registry Information:"
    get-registry-info $registry_url $registry_type
}

def wait-for-registry-health [registry_url: string] {
    mut retries = 30
    mut attempt = 1

    while $retries > 0 {
        print $"   Attempt ($attempt)/30..."

        let result = (do {
            http get $"http://($registry_url)/v2/"
        } | complete)

        if $result.exit_code == 0 {
            print "   ✓ Registry is healthy"
            return
        }

        $retries = ($retries - 1)
        $attempt = ($attempt + 1)
        sleep 2sec
    }

    error make {msg: "Registry failed to become healthy after 60 seconds"}
}

def create-default-namespaces [
    registry_url: string
    registry_type: string
    admin_password: string
] {
    let namespaces = [
        {
            name: "provisioning-extensions"
            description: "Extension packages (providers, taskservs, clusters)"
            public: false
        }
        {
            name: "provisioning-kcl"
            description: "KCL schema packages"
            public: false
        }
        {
            name: "provisioning-platform"
            description: "Platform service images (orchestrator, control-center, etc.)"
            public: false
        }
        {
            name: "provisioning-test"
            description: "Test images and artifacts"
            public: true
        }
    ]

    for namespace in $namespaces {
        print $"   Creating ($namespace.name)..."
        print $"     Description: ($namespace.description)"
        print $"     Public: ($namespace.public)"

        # Create namespace (method depends on registry type)
        match $registry_type {
            "zot" => {
                # Zot creates namespaces implicitly on first push
                print "     ✓ Will be created on first push"
            }
            "harbor" => {
                # Harbor requires API call to create project
                create-harbor-project $registry_url $namespace.name $namespace.description $namespace.public $admin_password
            }
            "distribution" => {
                # Distribution creates namespaces implicitly
                print "     ✓ Will be created on first push"
            }
            _ => {
                print $"     ⚠ Unknown registry type: ($registry_type)"
            }
        }
    }
}

def setup-access-policies [
    registry_url: string
    registry_type: string
    admin_password: string
] {
    # Configure access policies based on registry type
    match $registry_type {
        "zot" => {
            # Zot policies in config.json
            print "   ✓ Policies configured via config.json"
            print "     - provisioning-extensions: authenticated users"
            print "     - provisioning-kcl: authenticated users"
            print "     - provisioning-platform: private"
            print "     - provisioning-test: public read"
        }
        "harbor" => {
            # Harbor policies via API
            print "   Configuring Harbor policies..."
            setup-harbor-policies $registry_url $admin_password
        }
        "distribution" => {
            # Distribution uses htpasswd
            print "   ✓ Policies configured via htpasswd"
            print "     - All authenticated users: push/pull"
            print "     - Anonymous: pull only public repos"
        }
        _ => {
            print $"   ⚠ Unknown registry type: ($registry_type)"
        }
    }
}

def push-test-image [registry_url: string, registry_type: string] {
    print $"   Pushing test artifact to ($registry_url)/provisioning-test/hello:latest"

    # Create minimal OCI artifact using oras or docker
    let result = (do {
        # Try to push using docker if available
        docker pull hello-world:latest | complete
    } | complete)

    if $result.exit_code == 0 {
        let tag_result = (do {
            docker tag hello-world:latest $"($registry_url)/provisioning-test/hello:latest"
        } | complete)

        if $tag_result.exit_code == 0 {
            let push_result = (do {
                docker push $"($registry_url)/provisioning-test/hello:latest"
            } | complete)

            if $push_result.exit_code == 0 {
                print "   ✓ Test image pushed successfully"
                return
            }
        }
    }

    print "   ⚠ Could not push test image (docker may not be available)"
    print "   This is optional and can be done manually later"
}

def create-harbor-project [
    registry_url: string
    project_name: string
    description: string
    public: bool
    admin_password: string
] {
    # API call to create Harbor project
    let body = {
        project_name: $project_name
        metadata: {
            public: ($public | into string)
        }
        storage_limit: -1
    }

    let auth = $"admin:($admin_password)" | encode base64

    let result = (do {
        http post $"http://($registry_url)/api/v2.0/projects" $body --headers {
            "Authorization": $"Basic ($auth)"
            "Content-Type": "application/json"
        }
    } | complete)

    if $result.exit_code == 0 {
        print $"     ✓ Project created"
    } else {
        print $"     ⚠ Could not create project (may already exist)"
    }
}

def setup-harbor-policies [registry_url: string, admin_password: string] {
    # Setup Harbor policies via API
    let projects = ["provisioning-extensions", "provisioning-kcl", "provisioning-platform", "provisioning-test"]

    for project in $projects {
        print $"   Configuring policies for ($project)..."

        # Set retention policy
        let retention = {
            rules: [
                {
                    disabled: false
                    action: "retain"
                    params: {
                        latestPushedK: 10
                    }
                    tag_selectors: [
                        {
                            kind: "doublestar"
                            decoration: "matches"
                            pattern: "**"
                        }
                    ]
                    scope_selectors: {
                        repository: [
                            {
                                kind: "doublestar"
                                decoration: "matches"
                                pattern: "**"
                            }
                        ]
                    }
                }
            ]
            algorithm: "or"
        }

        # Additional Harbor-specific configurations
        print $"     ✓ Policies configured"
    }
}

def get-registry-info [registry_url: string, registry_type: string] -> table {
    let info = match $registry_type {
        "zot" => {
            [
                {key: "Type", value: "Zot (lightweight)"}
                {key: "Version", value: "2.0.1"}
                {key: "API", value: $"http://($registry_url)/v2/"}
                {key: "UI", value: $"http://($registry_url)/"}
                {key: "Metrics", value: $"http://($registry_url)/metrics"}
                {key: "Features", value: "Search, UI, Metrics, Scrub, GC"}
            ]
        }
        "harbor" => {
            [
                {key: "Type", value: "Harbor (full-featured)"}
                {key: "Version", value: "2.9.0"}
                {key: "API", value: $"http://($registry_url)/api/v2.0/"}
                {key: "UI", value: $"http://($registry_url)/"}
                {key: "Features", value: "Replication, Scanning, RBAC, Webhooks"}
            ]
        }
        "distribution" => {
            [
                {key: "Type", value: "Distribution (OCI standard)"}
                {key: "Version", value: "2.8"}
                {key: "API", value: $"http://($registry_url)/v2/"}
                {key: "UI", value: $"http://($registry_url):8080/"}
                {key: "Metrics", value: $"http://($registry_url):5001/metrics"}
                {key: "Features", value: "OCI-compliant, Lightweight, Fast"}
            ]
        }
        _ => {
            [
                {key: "Type", value: "Unknown"}
                {key: "URL", value: $registry_url}
            ]
        }
    }

    $info | table
}
