use serde::{Serialize, Deserialize};
use std::error::Error;
use std::path::Path;
use std::any::Any;

/// Represents a source of plugins
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub enum RepositorySource {
    HangarMC,
    SpigotMC,
    Modrinth,
    GitHub,
    BukkitDev,
    Custom(String),
}

/// Represents a plugin from a repository
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct RepositoryPlugin {
    pub id: String,               // Unique identifier in the repository
    pub name: String,             // Plugin name
    pub version: String,          // Latest version
    pub description: Option<String>,
    pub authors: Vec<String>,
    pub download_url: String,     // URL to download the plugin
    pub repository: RepositorySource,
    pub page_url: String,         // URL to the plugin page
    pub download_count: Option<u64>,
    pub last_updated: Option<String>,
    pub icon_url: Option<String>,
    pub minecraft_versions: Vec<String>,
    pub categories: Vec<String>,
    pub rating: Option<f32>,
    pub file_size: Option<u64>,
    pub file_hash: Option<String>,
    pub changelog: Option<String>, // Changelog information for latest version
}

/// Trait for crawler implementors with object safety
pub trait RepositoryCrawlerBase {
    fn as_any(&self) -> &dyn Any;
    fn get_repository_name(&self) -> RepositorySource;
}

/// Repository crawler search functionality
pub trait RepositoryCrawlerSearch: RepositoryCrawlerBase {
    fn search<'a>(&'a self, query: &'a str) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Vec<RepositoryPlugin>, Box<dyn Error + Send + Sync>>> + Send + 'a>>;
}

/// Repository crawler details functionality
pub trait RepositoryCrawlerDetails: RepositoryCrawlerBase {
    fn get_plugin_details<'a>(&'a self, plugin_id: &'a str) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<RepositoryPlugin, Box<dyn Error + Send + Sync>>> + Send + 'a>>;
}

/// Repository crawler versions functionality
pub trait RepositoryCrawlerVersions: RepositoryCrawlerBase {
    fn get_plugin_versions<'a>(&'a self, plugin_id: &'a str) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<Vec<String>, Box<dyn Error + Send + Sync>>> + Send + 'a>>;
}

/// Repository crawler download functionality
pub trait RepositoryCrawlerDownload: RepositoryCrawlerBase {
    fn download_plugin<'a>(&'a self, plugin_id: &'a str, version: &'a str, destination: &'a Path) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<String, Box<dyn Error + Send + Sync>>> + Send + 'a>>;
}

/// Represents a potential match from repositories for an installed plugin
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PotentialPluginMatch {
    pub name: String,
    pub version: String,
    pub repository: RepositorySource,
    pub repository_id: String,
    pub page_url: String,
    pub description: Option<String>,
    pub minecraft_versions: Vec<String>,
    pub download_count: Option<u64>,
}

/// Represents the result of a single plugin update operation
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SingleUpdateResult {
    pub original_file_path: String,
    pub plugin: Option<Plugin>, // None if error occurred
    pub error: Option<String>,
}

/// Represents the progress of bulk plugin updates
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BulkUpdateProgress {
    pub processed: usize,
    pub total: usize,
    pub current_plugin_name: String,
}

// Import required for SingleUpdateResult
use super::plugin::Plugin;