use std::sync::Arc;
use crate::infrastructure::database::Database;

use crate::business::errors::BusinessError;
use crate::data::models::project_template_binding::{
    ProjectTemplateBinding, BindingType, BindingStatus,
    CreateProjectTemplateBindingRequest, UpdateProjectTemplateBindingRequest,
    ProjectTemplateBindingQueryParams, ProjectTemplateBindingDetail,
    BatchCreateProjectTemplateBindingRequest, BatchDeleteProjectTemplateBindingRequest,
};
use crate::data::repositories::project_template_binding_repository::ProjectTemplateBindingRepository;

/// 项目-模板绑定业务服务
/// 遵循 Tauri 开发规范的业务逻辑层设计原则
pub struct ProjectTemplateBindingService {
    binding_repository: ProjectTemplateBindingRepository,
}

impl ProjectTemplateBindingService {
    /// 创建新的项目-模板绑定服务实例
    pub fn new(database: Arc<Database>) -> Result<Self, BusinessError> {
        Ok(Self {
            binding_repository: ProjectTemplateBindingRepository::new(database),
        })
    }

    /// 创建项目-模板绑定
    pub async fn create_binding(&self, request: CreateProjectTemplateBindingRequest) -> Result<ProjectTemplateBinding, BusinessError> {
        // 验证请求数据
        request.validate().map_err(|e| BusinessError::InvalidInput(e))?;

        // 检查绑定是否已存在
        if self.binding_repository.exists(&request.project_id, &request.template_id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))? {
            return Err(BusinessError::DuplicateName("项目和模板的绑定关系已存在".to_string()));
        }

        // 如果是主要绑定，检查项目是否已有主要绑定
        if request.binding_type == BindingType::Primary {
            let existing_primary = self.get_primary_binding_for_project(&request.project_id).await?;
            if existing_primary.is_some() {
                return Err(BusinessError::BusinessRuleViolation("项目已存在主要模板绑定，请先移除现有主要绑定".to_string()));
            }
        }

        // 创建绑定
        let binding = self.binding_repository.create(request)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        Ok(binding)
    }

    /// 更新项目-模板绑定
    pub async fn update_binding(&self, id: &str, request: UpdateProjectTemplateBindingRequest) -> Result<ProjectTemplateBinding, BusinessError> {
        // 验证请求数据
        request.validate().map_err(|e| BusinessError::InvalidInput(e))?;

        // 获取现有绑定
        let existing_binding = self.binding_repository.get_by_id(id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?
            .ok_or_else(|| BusinessError::NotFound("绑定不存在".to_string()))?;

        // 如果要更新为主要绑定，检查项目是否已有其他主要绑定
        if let Some(BindingType::Primary) = request.binding_type {
            if existing_binding.binding_type != BindingType::Primary {
                let existing_primary = self.get_primary_binding_for_project(&existing_binding.project_id).await?;
                if existing_primary.is_some() {
                    return Err(BusinessError::BusinessRuleViolation("项目已存在主要模板绑定，请先移除现有主要绑定".to_string()));
                }
            }
        }

        // 更新绑定
        let updated_binding = self.binding_repository.update(id, request)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?
            .ok_or_else(|| BusinessError::NotFound("绑定不存在".to_string()))?;

        Ok(updated_binding)
    }

    /// 删除项目-模板绑定
    pub async fn delete_binding(&self, id: &str) -> Result<(), BusinessError> {
        let deleted = self.binding_repository.delete(id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        if !deleted {
            return Err(BusinessError::NotFound("绑定不存在".to_string()));
        }

        Ok(())
    }

    /// 根据项目ID和模板ID删除绑定
    pub async fn delete_binding_by_project_and_template(&self, project_id: &str, template_id: &str) -> Result<(), BusinessError> {
        let deleted = self.binding_repository.delete_by_project_and_template(project_id, template_id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        if !deleted {
            return Err(BusinessError::NotFound("绑定不存在".to_string()));
        }

        Ok(())
    }

    /// 获取项目-模板绑定详情
    pub async fn get_binding(&self, id: &str) -> Result<ProjectTemplateBinding, BusinessError> {
        let binding = self.binding_repository.get_by_id(id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?
            .ok_or_else(|| BusinessError::NotFound("绑定不存在".to_string()))?;

        Ok(binding)
    }

    /// 查询项目-模板绑定列表
    pub async fn list_bindings(&self, params: ProjectTemplateBindingQueryParams) -> Result<Vec<ProjectTemplateBinding>, BusinessError> {
        let bindings = self.binding_repository.list(params)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        Ok(bindings)
    }

    /// 获取项目的模板列表
    pub async fn get_templates_by_project(&self, project_id: &str) -> Result<Vec<ProjectTemplateBindingDetail>, BusinessError> {
        let templates = self.binding_repository.get_templates_by_project(project_id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        Ok(templates)
    }

    /// 获取模板的项目列表
    pub async fn get_projects_by_template(&self, template_id: &str) -> Result<Vec<ProjectTemplateBindingDetail>, BusinessError> {
        let projects = self.binding_repository.get_projects_by_template(template_id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        Ok(projects)
    }

    /// 批量创建项目-模板绑定
    pub async fn batch_create_bindings(&self, request: BatchCreateProjectTemplateBindingRequest) -> Result<Vec<ProjectTemplateBinding>, BusinessError> {

        // 检查是否有重复的模板ID
        let mut unique_template_ids = std::collections::HashSet::new();
        for template_id in &request.template_ids {
            if !unique_template_ids.insert(template_id) {
                return Err(BusinessError::InvalidInput("模板ID列表中存在重复项".to_string()));
            }
        }

        // 检查是否已存在绑定
        for template_id in &request.template_ids {
            if self.binding_repository.exists(&request.project_id, template_id)
                .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))? {
                return Err(BusinessError::DuplicateName(format!("项目和模板 {} 的绑定关系已存在", template_id)));
            }
        }

        // 如果是主要绑定且有多个模板，只允许第一个为主要绑定
        if request.binding_type == BindingType::Primary && request.template_ids.len() > 1 {
            return Err(BusinessError::InvalidInput("批量创建时只能有一个主要绑定".to_string()));
        }

        // 如果是主要绑定，检查项目是否已有主要绑定
        if request.binding_type == BindingType::Primary {
            let existing_primary = self.get_primary_binding_for_project(&request.project_id).await?;
            if existing_primary.is_some() {
                return Err(BusinessError::BusinessRuleViolation("项目已存在主要模板绑定，请先移除现有主要绑定".to_string()));
            }
        }

        // 批量创建绑定
        let bindings = self.binding_repository.batch_create(request)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        Ok(bindings)
    }

    /// 批量删除项目-模板绑定
    pub async fn batch_delete_bindings(&self, request: BatchDeleteProjectTemplateBindingRequest) -> Result<u32, BusinessError> {
        let deleted_count = self.binding_repository.batch_delete(request)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        Ok(deleted_count)
    }

    /// 激活绑定
    pub async fn activate_binding(&self, id: &str) -> Result<ProjectTemplateBinding, BusinessError> {
        let mut binding = self.get_binding(id).await?;
        binding.activate();

        let updated_binding = self.binding_repository.update(id, UpdateProjectTemplateBindingRequest {
            binding_name: None,
            description: None,
            priority: None,
            binding_type: None,
            binding_status: Some(binding.binding_status.clone()),
            is_active: Some(binding.is_active),
        }).map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?
        .ok_or_else(|| BusinessError::NotFound("绑定不存在".to_string()))?;

        Ok(updated_binding)
    }

    /// 停用绑定
    pub async fn deactivate_binding(&self, id: &str) -> Result<ProjectTemplateBinding, BusinessError> {
        let mut binding = self.get_binding(id).await?;
        binding.deactivate();

        let updated_binding = self.binding_repository.update(id, UpdateProjectTemplateBindingRequest {
            binding_name: None,
            description: None,
            priority: None,
            binding_type: None,
            binding_status: Some(binding.binding_status.clone()),
            is_active: Some(binding.is_active),
        }).map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?
        .ok_or_else(|| BusinessError::NotFound("绑定不存在".to_string()))?;

        Ok(updated_binding)
    }

    /// 获取项目的主要模板绑定
    pub async fn get_primary_binding_for_project(&self, project_id: &str) -> Result<Option<ProjectTemplateBinding>, BusinessError> {
        let params = ProjectTemplateBindingQueryParams {
            project_id: Some(project_id.to_string()),
            template_id: None,
            binding_type: Some(BindingType::Primary),
            binding_status: Some(BindingStatus::Active),
            is_active: Some(true),
            limit: Some(1),
            offset: None,
        };

        let bindings = self.list_bindings(params).await?;
        Ok(bindings.into_iter().next())
    }

    /// 设置项目的主要模板
    pub async fn set_primary_template(&self, project_id: &str, template_id: &str) -> Result<ProjectTemplateBinding, BusinessError> {

        // 移除现有的主要绑定
        if let Some(existing_primary) = self.get_primary_binding_for_project(project_id).await? {
            self.update_binding(&existing_primary.id, UpdateProjectTemplateBindingRequest {
                binding_name: None,
                description: None,
                priority: None,
                binding_type: Some(BindingType::Secondary),
                binding_status: None,
                is_active: None,
            }).await?;
        }

        // 检查目标绑定是否存在
        if self.binding_repository.exists(project_id, template_id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))? {
            // 更新现有绑定为主要绑定
            let params = ProjectTemplateBindingQueryParams {
                project_id: Some(project_id.to_string()),
                template_id: Some(template_id.to_string()),
                binding_type: None,
                binding_status: None,
                is_active: None,
                limit: Some(1),
                offset: None,
            };

            let bindings = self.list_bindings(params).await?;
            if let Some(binding) = bindings.into_iter().next() {
                return self.update_binding(&binding.id, UpdateProjectTemplateBindingRequest {
                    binding_name: None,
                    description: None,
                    priority: None,
                    binding_type: Some(BindingType::Primary),
                    binding_status: Some(BindingStatus::Active),
                    is_active: Some(true),
                }).await;
            }
        } else {
            // 创建新的主要绑定
            return self.create_binding(CreateProjectTemplateBindingRequest {
                project_id: project_id.to_string(),
                template_id: template_id.to_string(),
                binding_name: None,
                description: None,
                priority: Some(0),
                binding_type: BindingType::Primary,
            }).await;
        }

        Err(BusinessError::NotFound("无法设置主要模板".to_string()))
    }

    /// 检查绑定是否存在
    pub async fn binding_exists(&self, project_id: &str, template_id: &str) -> Result<bool, BusinessError> {
        let exists = self.binding_repository.exists(project_id, template_id)
            .map_err(|e| BusinessError::BusinessRuleViolation(e.to_string()))?;

        Ok(exists)
    }
}
