#!/usr/bin/env nu

# User notification tool - sends update notifications and announcements
#
# Notifications:
# - Email notifications to subscribers
# - Slack/Discord announcements
# - Twitter/social media posts
# - RSS feed updates
# - Website banner updates
# - GitHub discussions/issues

use std log

def main [
    --channels: string = "slack"               # Notification channels: slack,discord,twitter,email,rss,website,all
    --release-version: string = ""             # Release version (auto-detected if empty)
    --message-template: string = ""            # Custom message template file
    --notification-config: string = ""         # Notification configuration file
    --recipient-list: string = ""              # Recipient list file (for email)
    --dry-run = false                          # Show what would be sent without sending
    --urgent                                   # Mark notifications as urgent/high priority
    --schedule: string = ""                    # Schedule notifications (e.g., "+1h", "2024-01-15T10:00:00")
    --verbose                                   # Enable verbose logging
]
{

    let repo_root = ($env.PWD | path dirname | path dirname | path dirname)

    # Determine release version if not provided
    let target_version = if $release_version == "" {
        detect_release_version $repo_root
    } else {
        $release_version
    }

    let notification_channels = if $channels == "all" {
        ["slack", "discord", "twitter", "email", "rss", "website"]
    } else {
        ($channels | split row "," | each { str trim })
    }

    let notification_config = {
        channels: $notification_channels
        release_version: $target_version
        message_template_file: (if $message_template == "" { "" } else { $message_template | path expand })
        notification_config_file: (if $notification_config == "" { "" } else { $notification_config | path expand })
        recipient_list_file: (if $recipient_list == "" { "" } else { $recipient_list | path expand })
        dry_run: $dry_run
        urgent: $urgent
        schedule: $schedule
        verbose: $verbose
        repo_root: $repo_root
    }

    log info $"Starting user notifications with config: ($notification_config)"

    # Load notification configuration
    let config_data = if $notification_config.notification_config_file != "" {
        load_notification_config $notification_config.notification_config_file
    } else {
        get_default_notification_config
    }

    # Generate release information
    let release_info = generate_release_info $notification_config $repo_root

    # Load or generate message templates
    let message_templates = if $notification_config.message_template_file != "" {
        load_message_templates $notification_config.message_template_file
    } else {
        generate_default_templates $release_info
    }

    # Check if notifications should be scheduled
    if $notification_config.schedule != "" {
        return schedule_notifications $notification_config $message_templates $config_data $release_info
    }

    # Send notifications to each channel
    let notification_results = $notification_config.channels | each {|channel|
        send_notification $channel $notification_config $message_templates $config_data $release_info
    }

    let summary = {
        total_channels: ($notification_config.channels | length)
        successful_notifications: ($notification_results | where status == "success" | length)
        failed_notifications: ($notification_results | where status == "failed" | length)
        skipped_notifications: ($notification_results | where status == "skipped" | length)
        release_version: $notification_config.release_version
        notification_config: $notification_config
        results: $notification_results
    }

    if $summary.failed_notifications > 0 {
        log error $"Notifications completed with ($summary.failed_notifications) failures"
        exit 1
    } else {
        if $notification_config.dry_run {
            log info $"Dry run completed - would send notifications to ($summary.total_channels) channels"
        } else {
            log info $"Notifications sent successfully to ($summary.successful_notifications) channels"
        }
    }

    return $summary
}

# Detect release version from git
def detect_release_version [repo_root: string]
{
    cd $repo_root

    try {
        # Try to get exact tag for current commit
        let exact_tag = (git describe --tags --exact-match HEAD 2>/dev/null | str trim)
        if $exact_tag != "" {
            return ($exact_tag | str replace "^v" "")
        }

        # Fallback to latest tag
        let latest_tag = (git describe --tags --abbrev=0 2>/dev/null | str trim)
        if $latest_tag != "" {
            return ($latest_tag | str replace "^v" "")
        }

        return "unknown"
    } catch {
        return "unknown"
    }
}

# Load notification configuration from file
def load_notification_config [config_file: string]
{
    if not ($config_file | path exists) {
        log warning $"Notification config file not found: ($config_file)"
        return (get_default_notification_config)
    }

    try {
        open $config_file
    } catch {|err|
        log warning $"Failed to load notification config: ($err.msg)"
        return (get_default_notification_config)
    }
}

# Get default notification configuration
def get_default_notification_config []
{
    {
        slack: {
            webhook_url: ""
            channel: "#general"
            username: "Provisioning Bot"
            icon_emoji: ":rocket:"
        }
        discord: {
            webhook_url: ""
            username: "Provisioning Bot"
            avatar_url: ""
        }
        twitter: {
            api_key: ""
            api_secret: ""
            access_token: ""
            access_token_secret: ""
        }
        email: {
            smtp_server: "smtp.gmail.com"
            smtp_port: 587
            username: ""
            password: ""
            from_address: "noreply@example.com"
            from_name: "Provisioning Team"
        }
        rss: {
            feed_file: "releases.xml"
            feed_title: "Provisioning Releases"
            feed_description: "Latest releases of the Provisioning system"
            feed_url: "https://example.com/releases.xml"
        }
        website: {
            banner_file: "release-banner.html"
            api_endpoint: ""
            api_key: ""
        }
    }
}

# Generate release information
def generate_release_info [notification_config: record, repo_root: string]
{
    cd $repo_root

    let version = $notification_config.release_version
    let tag_name = $"v($version)"

    # Get release date
    let release_date = try {
        git log -1 --format=%cd --date=short $tag_name 2>/dev/null | str trim
    } catch {
        date now | format date "%Y-%m-%d"
    }

    # Get changelog
    let changelog = try {
        get_changelog_summary $repo_root $tag_name
    } catch {
        "Bug fixes and improvements"
    }

    # Get download URLs
    let download_base_url = $"https://github.com/your-org/provisioning/releases/download/($tag_name)"
    let download_urls = {
        linux: $"($download_base_url)/provisioning-($version)-linux-complete.tar.gz"
        macos: $"($download_base_url)/provisioning-($version)-macos-complete.tar.gz"
        windows: $"($download_base_url)/provisioning-($version)-windows-complete.zip"
    }

    # Get release notes URL
    let release_url = $"https://github.com/your-org/provisioning/releases/tag/($tag_name)"

    {
        version: $version
        tag_name: $tag_name
        release_date: $release_date
        changelog: $changelog
        download_urls: $download_urls
        release_url: $release_url
        is_major: (is_major_version $version)
        is_security: (is_security_release $changelog)
    }
}

# Get changelog summary for a specific tag
def get_changelog_summary [repo_root: string, tag_name: string]
{
    # Get previous tag
    let previous_tag = try {
        git describe --tags --abbrev=0 $"($tag_name)^" 2>/dev/null | str trim
    } catch {
        ""
    }

    # Get commits between tags
    let commit_range = if $previous_tag != "" {
        $"($previous_tag)..($tag_name)"
    } else {
        $tag_name
    }

    let commits = try {
        git log $commit_range --pretty=format:"%s" --no-merges | lines | where $it != ""
    } catch {
        []
    }

    # Summarize changes
    let features = ($commits | where ($it =~ "^feat"))
    let fixes = ($commits | where ($it =~ "^fix"))
    let summary_parts = []

    if ($features | length) > 0 {
        $summary_parts = ($summary_parts | append $"($features | length) new features")
    }

    if ($fixes | length) > 0 {
        $summary_parts = ($summary_parts | append $"($fixes | length) bug fixes")
    }

    if ($summary_parts | length) > 0 {
        return ($summary_parts | str join ", ")
    } else {
        return "Bug fixes and improvements"
    }
}

# Check if version is a major release
def is_major_version [version: string]
{
    let parts = ($version | split row ".")
    if ($parts | length) >= 3 {
        let minor = ($parts | get 1)
        let patch = ($parts | get 2)
        return ($minor == "0" and $patch == "0")
    }
    return false
}

# Check if release contains security fixes
def is_security_release [changelog: string]
{
    ($changelog | str downcase | str contains "security") or
    ($changelog | str downcase | str contains "vulnerability") or
    ($changelog | str downcase | str contains "cve")
}

# Load message templates from file
def load_message_templates [template_file: string]
{
    if not ($template_file | path exists) {
        log warning $"Template file not found: ($template_file)"
        return {}
    }

    try {
        open $template_file
    } catch {|err|
        log warning $"Failed to load templates: ($err.msg)"
        return {}
    }
}

# Generate default message templates
def generate_default_templates [release_info: record]
{
    let urgency_text = if $release_info.is_security { "🚨 Security Update " } else if $release_info.is_major { "🎉 Major Release " } else { "" }
    let emoji = if $release_info.is_security { "🔒" } else if $release_info.is_major { "🎉" } else { "🚀" }

    {
        slack: {
            text: $"($urgency_text)($emoji) Provisioning v($release_info.version) Released!"
            attachments: [
                {
                    color: (if $release_info.is_security { "danger" } else { "good" })
                    fields: [
                        { title: "Version", value: $release_info.version, short: true }
                        { title: "Release Date", value: $release_info.release_date, short: true }
                        { title: "Changes", value: $release_info.changelog, short: false }
                    ]
                    actions: [
                        { type: "button", text: "Download", url: $release_info.download_urls.linux }
                        { type: "button", text: "Release Notes", url: $release_info.release_url }
                    ]
                }
            ]
        }
        discord: {
            content: $"($urgency_text)($emoji) **Provisioning v($release_info.version)** has been released!"
            embeds: [
                {
                    title: $"Release v($release_info.version)"
                    description: $release_info.changelog
                    color: (if $release_info.is_security { 15158332 } else { 3066993 })  # Red or Green
                    fields: [
                        { name: "Release Date", value: $release_info.release_date, inline: true }
                        { name: "Downloads", value: $"[Linux]((\"($release_info.download_urls.linux)\")) | [macOS]((\"($release_info.download_urls.macos)\")) | [Windows]((\"($release_info.download_urls.windows)\"))", inline: false }
                    ]
                    url: $release_info.release_url
                    timestamp: (date now | format date "%Y-%m-%dT%H:%M:%S.000Z")
                }
            ]
        }
        twitter: {
            status: $"($urgency_text)($emoji) Provisioning v($release_info.version) is now available! ($release_info.changelog) Download: ($release_info.release_url) #CloudNative #Infrastructure #DevOps"
        }
        email: {
            subject: $"($urgency_text)Provisioning v($release_info.version) Released"
            body: $"Dear Provisioning Users,

We're excited to announce the release of Provisioning v($release_info.version)!

**What's New:**
($release_info.changelog)

**Downloads:**
- Linux: ($release_info.download_urls.linux)
- macOS: ($release_info.download_urls.macos)
- Windows: ($release_info.download_urls.windows)

**Release Notes:**
For detailed information about this release, please visit:
($release_info.release_url)

Thank you for using Provisioning!

Best regards,
The Provisioning Team"
        }
    }
}

# Schedule notifications for later
def schedule_notifications [
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info $"Scheduling notifications for: ($notification_config.schedule)"

    # In a real implementation, this would use a job scheduler like cron
    # For now, we'll just return the scheduled job information

    {
        status: "scheduled"
        schedule_time: $notification_config.schedule
        channels: $notification_config.channels
        release_version: $notification_config.release_version
        message: "Notifications scheduled successfully"
    }
}

# Send notification to specific channel
def send_notification [
    channel: string
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info $"Sending notification to: ($channel)"

    let start_time = (date now)

    match $channel {
        "slack" => { send_slack_notification $notification_config $message_templates $config_data $release_info }
        "discord" => { send_discord_notification $notification_config $message_templates $config_data $release_info }
        "twitter" => { send_twitter_notification $notification_config $message_templates $config_data $release_info }
        "email" => { send_email_notification $notification_config $message_templates $config_data $release_info }
        "rss" => { update_rss_feed $notification_config $message_templates $config_data $release_info }
        "website" => { update_website_banner $notification_config $message_templates $config_data $release_info }
        _ => {
            log warning $"Unknown notification channel: ($channel)"
            {
                channel: $channel
                status: "failed"
                reason: "unknown channel"
                duration: ((date now) - $start_time)
            }
        }
    }
}

# Send Slack notification
def send_slack_notification [
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info "Sending Slack notification..."

    let start_time = (date now)
    let slack_config = ($config_data.slack)

    if $slack_config.webhook_url == "" {
        return {
            channel: "slack"
            status: "failed"
            reason: "webhook URL not configured"
            duration: ((date now) - $start_time)
        }
    }

    if $notification_config.dry_run {
        return {
            channel: "slack"
            status: "success"
            message_preview: $message_templates.slack.text
            dry_run: true
            duration: ((date now) - $start_time)
        }
    }

    try {
        let payload = {
            channel: $slack_config.channel
            username: $slack_config.username
            icon_emoji: $slack_config.icon_emoji
            text: $message_templates.slack.text
            attachments: $message_templates.slack.attachments
        }

        let curl_result = (curl -X POST -H "Content-type: application/json" --data ($payload | to json) $slack_config.webhook_url | complete)

        if $curl_result.exit_code == 0 {
            {
                channel: "slack"
                status: "success"
                webhook_url: $slack_config.webhook_url
                duration: ((date now) - $start_time)
            }
        } else {
            {
                channel: "slack"
                status: "failed"
                reason: $curl_result.stderr
                duration: ((date now) - $start_time)
            }
        }

    } catch {|err|
        {
            channel: "slack"
            status: "failed"
            reason: $err.msg
            duration: ((date now) - $start_time)
        }
    }
}

# Send Discord notification
def send_discord_notification [
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info "Sending Discord notification..."

    let start_time = (date now)
    let discord_config = ($config_data.discord)

    if $discord_config.webhook_url == "" {
        return {
            channel: "discord"
            status: "failed"
            reason: "webhook URL not configured"
            duration: ((date now) - $start_time)
        }
    }

    if $notification_config.dry_run {
        return {
            channel: "discord"
            status: "success"
            message_preview: $message_templates.discord.content
            dry_run: true
            duration: ((date now) - $start_time)
        }
    }

    try {
        let payload = {
            username: $discord_config.username
            avatar_url: $discord_config.avatar_url
            content: $message_templates.discord.content
            embeds: $message_templates.discord.embeds
        }

        let curl_result = (curl -X POST -H "Content-type: application/json" --data ($payload | to json) $discord_config.webhook_url | complete)

        if $curl_result.exit_code == 0 {
            {
                channel: "discord"
                status: "success"
                webhook_url: $discord_config.webhook_url
                duration: ((date now) - $start_time)
            }
        } else {
            {
                channel: "discord"
                status: "failed"
                reason: $curl_result.stderr
                duration: ((date now) - $start_time)
            }
        }

    } catch {|err|
        {
            channel: "discord"
            status: "failed"
            reason: $err.msg
            duration: ((date now) - $start_time)
        }
    }
}

# Send Twitter notification
def send_twitter_notification [
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info "Sending Twitter notification..."

    let start_time = (date now)

    if $notification_config.dry_run {
        return {
            channel: "twitter"
            status: "success"
            tweet_preview: $message_templates.twitter.status
            dry_run: true
            duration: ((date now) - $start_time)
        }
    }

    # Twitter API integration would be implemented here
    log warning "Twitter notification not fully implemented - requires API setup"

    {
        channel: "twitter"
        status: "skipped"
        reason: "not fully implemented"
        duration: ((date now) - $start_time)
    }
}

# Send email notification
def send_email_notification [
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info "Sending email notification..."

    let start_time = (date now)

    if $notification_config.dry_run {
        return {
            channel: "email"
            status: "success"
            subject_preview: $message_templates.email.subject
            dry_run: true
            duration: ((date now) - $start_time)
        }
    }

    # Email sending would be implemented here using SMTP
    log warning "Email notification not fully implemented - requires SMTP configuration"

    {
        channel: "email"
        status: "skipped"
        reason: "not fully implemented"
        duration: ((date now) - $start_time)
    }
}

# Update RSS feed
def update_rss_feed [
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info "Updating RSS feed..."

    let start_time = (date now)
    let rss_config = ($config_data.rss)

    if $notification_config.dry_run {
        return {
            channel: "rss"
            status: "success"
            feed_file: $rss_config.feed_file
            dry_run: true
            duration: ((date now) - $start_time)
        }
    }

    try {
        let rss_item = generate_rss_item $release_info
        # RSS feed update logic would be implemented here
        log warning "RSS feed update not fully implemented"

        {
            channel: "rss"
            status: "skipped"
            reason: "not fully implemented"
            feed_file: $rss_config.feed_file
            duration: ((date now) - $start_time)
        }

    } catch {|err|
        {
            channel: "rss"
            status: "failed"
            reason: $err.msg
            duration: ((date now) - $start_time)
        }
    }
}

# Update website banner
def update_website_banner [
    notification_config: record
    message_templates: record
    config_data: record
    release_info: record
]
{
    log info "Updating website banner..."

    let start_time = (date now)

    if $notification_config.dry_run {
        return {
            channel: "website"
            status: "success"
            dry_run: true
            duration: ((date now) - $start_time)
        }
    }

    # Website banner update logic would be implemented here
    log warning "Website banner update not fully implemented"

    {
        channel: "website"
        status: "skipped"
        reason: "not fully implemented"
        duration: ((date now) - $start_time)
    }
}

# Generate RSS item for release
def generate_rss_item [release_info: record]
{
    $"<item>
    <title>Provisioning v($release_info.version) Released</title>
    <description>($release_info.changelog)</description>
    <link>($release_info.release_url)</link>
    <guid>($release_info.release_url)</guid>
    <pubDate>(date now | format date "%a, %d %b %Y %H:%M:%S %z")</pubDate>
  </item>"
}

# Show notification status
def "main status" [] {
    let curl_available = (try { curl --version | complete } catch { { exit_code: 1 } }).exit_code == 0

    let repo_root = ($env.PWD | path dirname | path dirname | path dirname)
    let current_version = (detect_release_version $repo_root)

    {
        current_version: $current_version
        available_tools: {
            curl: $curl_available
        }
        supported_channels: ["slack", "discord", "twitter", "email", "rss", "website"]
        implemented_channels: ["slack", "discord"]  # Only these are fully implemented
    }
}

# Initialize notification configuration
def "main init-config" [output_file: string = "notification-config.toml"] {
    let config_template = $"# Notification Configuration

[slack]
webhook_url = \"\"  # Your Slack webhook URL
channel = \"#general\"
username = \"Provisioning Bot\"
icon_emoji = \":rocket:\"

[discord]
webhook_url = \"\"  # Your Discord webhook URL
username = \"Provisioning Bot\"
avatar_url = \"\"

[twitter]
api_key = \"\"
api_secret = \"\"
access_token = \"\"
access_token_secret = \"\"

[email]
smtp_server = \"smtp.gmail.com\"
smtp_port = 587
username = \"\"
password = \"\"
from_address = \"noreply@example.com\"
from_name = \"Provisioning Team\"

[rss]
feed_file = \"releases.xml\"
feed_title = \"Provisioning Releases\"
feed_description = \"Latest releases of the Provisioning system\"
feed_url = \"https://example.com/releases.xml\"

[website]
banner_file = \"release-banner.html\"
api_endpoint = \"\"
api_key = \"\"
"

    $config_template | save $output_file
    log info $"Generated notification configuration template: ($output_file)"

    {
        config_file: $output_file
        channels_configured: 6
        template_generated: true
    }
}

# Test notification to specific channel
def "main test" [
    channel: string = "slack"                  # Channel to test
    --config: string = ""                      # Configuration file
] {
    log info $"Testing notification to: ($channel)"

    let test_release_info = {
        version: "1.0.0-test"
        tag_name: "v1.0.0-test"
        release_date: (date now | format date "%Y-%m-%d")
        changelog: "Test notification"
        download_urls: {
            linux: "https://example.com/linux.tar.gz"
            macos: "https://example.com/macos.tar.gz"
            windows: "https://example.com/windows.zip"
        }
        release_url: "https://github.com/example/test"
        is_major: false
        is_security: false
    }

    let test_config = {
        channels: [$channel]
        release_version: "1.0.0-test"
        dry_run: false
        verbose: true
    }

    let config_data = if $config != "" {
        load_notification_config $config
    } else {
        get_default_notification_config
    }

    let templates = generate_default_templates $test_release_info

    send_notification $channel $test_config $templates $config_data $test_release_info
}
