use anyhow::Result;
use chrono::NaiveDate;
use clap::{Parser, Subcommand};
use reqwest::Client;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Args {
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    /// Upload quarterly schedule from JSON file
    Schedule {
        /// JSON file containing schedule data
        #[arg(short, long)]
        file: PathBuf,
    },
    /// Upload yearly conference data (offering focuses and sunset times)
    Conference {
        /// JSON file containing conference data
        #[arg(short, long)]
        file: PathBuf,
    },
    /// Generate sample JSON files for reference
    GenerateSamples,
}

#[derive(Debug, Serialize, Deserialize)]
struct ScheduleEntry {
    date: String,
    personnel: PersonnelData,
}

#[derive(Debug, Serialize, Deserialize)]
struct PersonnelData {
    ss_leader: String,
    ss_teacher: String,
    mission_story: String,
    song_leader: String,
    announcements: String,
    offering: String,
    special_music: String,
    speaker: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ConferenceEntry {
    date: String,
    offering_focus: String,
    sunset_tonight: String,
    sunset_next_friday: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct ScheduleUpload {
    schedule: Vec<ScheduleEntry>,
}

#[derive(Debug, Serialize, Deserialize)]
struct ConferenceUpload {
    conference_data: Vec<ConferenceEntry>,
}

#[derive(Debug, Deserialize)]
struct ApiResponse {
    success: bool,
    message: Option<String>,
}

async fn upload_schedule(file_path: &PathBuf) -> Result<()> {
    let content = std::fs::read_to_string(file_path)?;
    let schedule_data: ScheduleUpload = serde_json::from_str(&content)?;
    
    let auth_token = std::env::var("BULLETIN_API_TOKEN")
        .map_err(|_| anyhow::anyhow!("BULLETIN_API_TOKEN not found in environment"))?;
    
    let client = Client::new();
    let response = client
        .post("https://api.rockvilletollandsda.church/api/admin/schedule")
        .header("Authorization", format!("Bearer {}", auth_token))
        .json(&schedule_data)
        .send()
        .await?;
    
    if response.status().is_success() {
        let api_response: ApiResponse = response.json().await?;
        if api_response.success {
            println!("✅ Schedule uploaded successfully!");
            println!("   Uploaded {} schedule entries", schedule_data.schedule.len());
        } else {
            println!("❌ API returned error: {:?}", api_response.message);
        }
    } else {
        let error_text = response.text().await?;
        println!("❌ Upload failed: {}", error_text);
    }
    
    Ok(())
}

async fn upload_conference_data(file_path: &PathBuf) -> Result<()> {
    let content = std::fs::read_to_string(file_path)?;
    let conference_data: ConferenceUpload = serde_json::from_str(&content)?;
    
    let auth_token = std::env::var("BULLETIN_API_TOKEN")
        .map_err(|_| anyhow::anyhow!("BULLETIN_API_TOKEN not found in environment"))?;
    
    let client = Client::new();
    let response = client
        .post("https://api.rockvilletollandsda.church/api/admin/conference-data")
        .header("Authorization", format!("Bearer {}", auth_token))
        .json(&conference_data)
        .send()
        .await?;
    
    if response.status().is_success() {
        let api_response: ApiResponse = response.json().await?;
        if api_response.success {
            println!("✅ Conference data uploaded successfully!");
            println!("   Uploaded {} conference entries", conference_data.conference_data.len());
        } else {
            println!("❌ API returned error: {:?}", api_response.message);
        }
    } else {
        let error_text = response.text().await?;
        println!("❌ Upload failed: {}", error_text);
    }
    
    Ok(())
}

fn generate_sample_files() -> Result<()> {
    // Generate sample schedule JSON
    let sample_schedule = ScheduleUpload {
        schedule: vec![
            ScheduleEntry {
                date: "2025-01-04".to_string(),
                personnel: PersonnelData {
                    ss_leader: "Wayne Tino".to_string(),
                    ss_teacher: "Orville Castillo".to_string(),
                    mission_story: "Jerry Travers".to_string(),
                    song_leader: "Lisa Wroniak".to_string(),
                    announcements: "Orville Castillo".to_string(),
                    offering: "Audley Brown".to_string(),
                    special_music: "Michelle Maitland".to_string(),
                    speaker: "Pastor Joseph Piresson".to_string(),
                }
            },
            ScheduleEntry {
                date: "2025-01-11".to_string(),
                personnel: PersonnelData {
                    ss_leader: "Wayne Tino".to_string(),
                    ss_teacher: "Orville Castillo".to_string(),
                    mission_story: "Jerry Travers".to_string(),
                    song_leader: "Lisa Wroniak".to_string(),
                    announcements: "Orville Castillo".to_string(),
                    offering: "Audley Brown".to_string(),
                    special_music: "Michelle Maitland".to_string(),
                    speaker: "Guest Speaker".to_string(),
                }
            }
        ]
    };
    
    let schedule_json = serde_json::to_string_pretty(&sample_schedule)?;
    std::fs::write("sample_schedule.json", schedule_json)?;
    println!("📄 Generated sample_schedule.json");
    
    // Generate sample conference data JSON
    let sample_conference = ConferenceUpload {
        conference_data: vec![
            ConferenceEntry {
                date: "2025-01-04".to_string(),
                offering_focus: "Local Church Budget".to_string(),
                sunset_tonight: "5:15 pm".to_string(),
                sunset_next_friday: "5:16 pm".to_string(),
            },
            ConferenceEntry {
                date: "2025-01-11".to_string(),
                offering_focus: "World Budget".to_string(),
                sunset_tonight: "5:16 pm".to_string(),
                sunset_next_friday: "5:18 pm".to_string(),
            }
        ]
    };
    
    let conference_json = serde_json::to_string_pretty(&sample_conference)?;
    std::fs::write("sample_conference.json", conference_json)?;
    println!("📄 Generated sample_conference.json");
    
    println!("\n📋 Sample files created! Edit them and upload with:");
    println!("   cargo run -- schedule --file sample_schedule.json");
    println!("   cargo run -- conference --file sample_conference.json");
    
    Ok(())
}

#[tokio::main]
async fn main() -> Result<()> {
    dotenvy::dotenv().ok();
    
    let args = Args::parse();
    
    match args.command {
        Commands::Schedule { file } => {
            println!("📤 Uploading schedule from: {}", file.display());
            upload_schedule(&file).await?;
        }
        Commands::Conference { file } => {
            println!("📤 Uploading conference data from: {}", file.display());
            upload_conference_data(&file).await?;
        }
        Commands::GenerateSamples => {
            generate_sample_files()?;
        }
    }
    
    Ok(())
}