//! Example showing idempotent DNS sync for CI/CD workflows.

use lmrc_cloudflare::{
    ChangeAction, CloudflareClient,
    dns::{DnsRecordBuilder, RecordType},
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Get configuration from environment
    let api_token = std::env::var("CLOUDFLARE_API_TOKEN")
        .expect("CLOUDFLARE_API_TOKEN environment variable must be set");
    let zone_name =
        std::env::var("CLOUDFLARE_ZONE").expect("CLOUDFLARE_ZONE environment variable must be set");

    // Create client
    println!("Connecting to Cloudflare...");
    let client = CloudflareClient::new(api_token)?;

    // Get zone ID
    let zone_id = client.zones().get_zone_id(&zone_name).await?;
    println!("Found zone: {} ({})", zone_name, zone_id);

    // Define desired DNS records state
    let desired_records = vec![
        DnsRecordBuilder::new()
            .name(format!("api.{}", zone_name))
            .record_type(RecordType::A)
            .content(std::env::var("API_SERVER_IP").unwrap_or_else(|_| "192.0.2.1".to_string()))
            .proxied(true)
            .ttl(1)
            .comment("API server - managed by CI/CD"),
        DnsRecordBuilder::new()
            .name(format!("www.{}", zone_name))
            .record_type(RecordType::CNAME)
            .content(zone_name.clone())
            .proxied(true)
            .ttl(1)
            .comment("WWW redirect - managed by CI/CD"),
    ];

    // First do a dry run to see what would change
    println!("\n=== Dry run - checking what would change ===");
    let changes = client
        .dns()
        .sync_records(&zone_id)
        .records(desired_records.clone())
        .dry_run(true)
        .send()
        .await?;

    let mut has_changes = false;
    for change in &changes {
        match change.action {
            ChangeAction::Create => {
                println!("  [CREATE] {}", change.description);
                has_changes = true;
            }
            ChangeAction::Update => {
                println!("  [UPDATE] {}", change.description);
                has_changes = true;
            }
            ChangeAction::NoChange => {
                println!("  [OK] {}", change.description);
            }
            _ => {}
        }
    }

    if !has_changes {
        println!("\nNo changes needed - DNS records are already in desired state!");
        return Ok(());
    }

    // Apply the changes
    println!("\n=== Applying changes ===");
    let changes = client
        .dns()
        .sync_records(&zone_id)
        .records(desired_records)
        .dry_run(false)
        .send()
        .await?;

    let applied_changes = changes.iter().filter(|c| c.action.is_mutating()).count();
    println!("\nSuccessfully applied {} changes!", applied_changes);

    Ok(())
}
