use rusqlite::{Result, Row};
use std::sync::Arc;
use chrono::{DateTime, Utc};
use crate::infrastructure::database::Database;

use crate::data::models::project_template_binding::{
    ProjectTemplateBinding, BindingType, BindingStatus,
    CreateProjectTemplateBindingRequest, UpdateProjectTemplateBindingRequest,
    ProjectTemplateBindingQueryParams, ProjectTemplateBindingDetail,
    BatchCreateProjectTemplateBindingRequest, BatchDeleteProjectTemplateBindingRequest,
};

/// 项目-模板绑定数据库操作仓储
/// 遵循 Tauri 开发规范的数据访问层设计原则
pub struct ProjectTemplateBindingRepository {
    database: Arc<Database>,
}

impl ProjectTemplateBindingRepository {
    /// 创建新的项目-模板绑定仓储实例
    pub fn new(database: Arc<Database>) -> Self {
        Self { database }
    }

    /// 创建项目-模板绑定
    pub fn create(&self, request: CreateProjectTemplateBindingRequest) -> Result<ProjectTemplateBinding> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let binding = ProjectTemplateBinding::new(
            request.project_id,
            request.template_id,
            request.binding_type,
        );

        let mut final_binding = binding;
        if let Some(name) = request.binding_name {
            final_binding.binding_name = Some(name);
        }
        if let Some(desc) = request.description {
            final_binding.description = Some(desc);
        }
        if let Some(priority) = request.priority {
            final_binding.priority = priority;
        }

        conn.execute(
            "INSERT INTO project_template_bindings (
                id, project_id, template_id, binding_name, description, priority,
                is_active, binding_type, binding_status, metadata, created_at, updated_at
            ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)",
            rusqlite::params![
                &final_binding.id,
                &final_binding.project_id,
                &final_binding.template_id,
                &final_binding.binding_name,
                &final_binding.description,
                &final_binding.priority.to_string(),
                &(final_binding.is_active as i32).to_string(),
                &serde_json::to_string(&final_binding.binding_type).unwrap(),
                &serde_json::to_string(&final_binding.binding_status).unwrap(),
                &final_binding.metadata,
                &final_binding.created_at.to_rfc3339(),
                &final_binding.updated_at.to_rfc3339(),
            ],
        )?;

        Ok(final_binding)
    }

    /// 根据ID获取项目-模板绑定
    pub fn get_by_id(&self, id: &str) -> Result<Option<ProjectTemplateBinding>> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let mut stmt = conn.prepare(
            "SELECT id, project_id, template_id, binding_name, description, priority,
                    is_active, binding_type, binding_status, metadata, created_at, updated_at
             FROM project_template_bindings WHERE id = ?1"
        )?;

        let binding_iter = stmt.query_map([id], |row| {
            self.row_to_binding(row)
        })?;

        for binding in binding_iter {
            return Ok(Some(binding?));
        }

        Ok(None)
    }

    /// 更新项目-模板绑定
    pub fn update(&self, id: &str, request: UpdateProjectTemplateBindingRequest) -> Result<Option<ProjectTemplateBinding>> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        // 首先获取现有绑定
        if let Some(mut binding) = self.get_by_id(id)? {
            // 更新字段
            binding.update(
                request.binding_name,
                request.description,
                request.priority,
                request.binding_type,
                request.binding_status,
            );

            if let Some(is_active) = request.is_active {
                binding.is_active = is_active;
            }

            // 保存到数据库
            conn.execute(
                "UPDATE project_template_bindings SET
                    binding_name = ?1, description = ?2, priority = ?3,
                    is_active = ?4, binding_type = ?5, binding_status = ?6,
                    updated_at = ?7
                 WHERE id = ?8",
                rusqlite::params![
                    &binding.binding_name,
                    &binding.description,
                    binding.priority as i32,
                    binding.is_active as i32,
                    &serde_json::to_string(&binding.binding_type).unwrap(),
                    &serde_json::to_string(&binding.binding_status).unwrap(),
                    &binding.updated_at.to_rfc3339(),
                    id,
                ],
            )?;

            Ok(Some(binding))
        } else {
            Ok(None)
        }
    }

    /// 删除项目-模板绑定
    pub fn delete(&self, id: &str) -> Result<bool> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let rows_affected = conn.execute(
            "DELETE FROM project_template_bindings WHERE id = ?1",
            [id],
        )?;

        Ok(rows_affected > 0)
    }

    /// 根据项目ID和模板ID删除绑定
    pub fn delete_by_project_and_template(&self, project_id: &str, template_id: &str) -> Result<bool> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let rows_affected = conn.execute(
            "DELETE FROM project_template_bindings WHERE project_id = ?1 AND template_id = ?2",
            [project_id, template_id],
        )?;

        Ok(rows_affected > 0)
    }

    /// 查询项目-模板绑定列表
    pub fn list(&self, params: ProjectTemplateBindingQueryParams) -> Result<Vec<ProjectTemplateBinding>> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let mut query = "SELECT id, project_id, template_id, binding_name, description, priority,
                                is_active, binding_type, binding_status, metadata, created_at, updated_at
                         FROM project_template_bindings WHERE 1=1".to_string();
        let mut query_params: Vec<String> = Vec::new();

        if let Some(project_id) = params.project_id {
            query.push_str(" AND project_id = ?");
            query_params.push(project_id);
        }

        if let Some(template_id) = params.template_id {
            query.push_str(" AND template_id = ?");
            query_params.push(template_id);
        }

        if let Some(binding_type) = params.binding_type {
            query.push_str(" AND binding_type = ?");
            query_params.push(serde_json::to_string(&binding_type).unwrap());
        }

        if let Some(binding_status) = params.binding_status {
            query.push_str(" AND binding_status = ?");
            query_params.push(serde_json::to_string(&binding_status).unwrap());
        }

        if let Some(is_active) = params.is_active {
            query.push_str(" AND is_active = ?");
            query_params.push(if is_active { "1" } else { "0" }.to_string());
        }

        query.push_str(" ORDER BY priority ASC, created_at DESC");

        if let Some(limit) = params.limit {
            query.push_str(&format!(" LIMIT {}", limit));
        }

        if let Some(offset) = params.offset {
            query.push_str(&format!(" OFFSET {}", offset));
        }

        let mut stmt = conn.prepare(&query)?;
        let params_refs: Vec<&dyn rusqlite::ToSql> = query_params.iter().map(|s| s as &dyn rusqlite::ToSql).collect();
        let binding_iter = stmt.query_map(
            params_refs.as_slice(),
            |row| self.row_to_binding(row)
        )?;

        let mut bindings = Vec::new();
        for binding in binding_iter {
            bindings.push(binding?);
        }

        Ok(bindings)
    }

    /// 获取项目的模板列表
    pub fn get_templates_by_project(&self, project_id: &str) -> Result<Vec<ProjectTemplateBindingDetail>> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let mut stmt = conn.prepare(
            "SELECT ptb.id, ptb.project_id, ptb.template_id, ptb.binding_name, ptb.description, ptb.priority,
                    ptb.is_active, ptb.binding_type, ptb.binding_status, ptb.metadata, ptb.created_at, ptb.updated_at,
                    p.name as project_name, t.name as template_name, t.description as template_description
             FROM project_template_bindings ptb
             JOIN projects p ON ptb.project_id = p.id
             JOIN templates t ON ptb.template_id = t.id
             WHERE ptb.project_id = ?1
             ORDER BY ptb.priority ASC, ptb.created_at DESC"
        )?;

        let detail_iter = stmt.query_map([project_id], |row| {
            let binding = self.row_to_binding(row)?;
            let project_name: String = row.get("project_name")?;
            let template_name: String = row.get("template_name")?;
            let template_description: Option<String> = row.get("template_description")?;

            Ok(ProjectTemplateBindingDetail {
                binding,
                project_name,
                template_name,
                template_description,
            })
        })?;

        let mut details = Vec::new();
        for detail in detail_iter {
            details.push(detail?);
        }

        Ok(details)
    }

    /// 获取模板的项目列表
    pub fn get_projects_by_template(&self, template_id: &str) -> Result<Vec<ProjectTemplateBindingDetail>> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let mut stmt = conn.prepare(
            "SELECT ptb.id, ptb.project_id, ptb.template_id, ptb.binding_name, ptb.description, ptb.priority,
                    ptb.is_active, ptb.binding_type, ptb.binding_status, ptb.metadata, ptb.created_at, ptb.updated_at,
                    p.name as project_name, t.name as template_name, t.description as template_description
             FROM project_template_bindings ptb
             JOIN projects p ON ptb.project_id = p.id
             JOIN templates t ON ptb.template_id = t.id
             WHERE ptb.template_id = ?1
             ORDER BY ptb.priority ASC, ptb.created_at DESC"
        )?;

        let detail_iter = stmt.query_map([template_id], |row| {
            let binding = self.row_to_binding(row)?;
            let project_name: String = row.get("project_name")?;
            let template_name: String = row.get("template_name")?;
            let template_description: Option<String> = row.get("template_description")?;

            Ok(ProjectTemplateBindingDetail {
                binding,
                project_name,
                template_name,
                template_description,
            })
        })?;

        let mut details = Vec::new();
        for detail in detail_iter {
            details.push(detail?);
        }

        Ok(details)
    }

    /// 批量创建项目-模板绑定
    pub fn batch_create(&self, request: BatchCreateProjectTemplateBindingRequest) -> Result<Vec<ProjectTemplateBinding>> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        let mut bindings = Vec::new();
        
        let mut priority = request.priority_start.unwrap_or(0);
        
        for template_id in request.template_ids {
            let binding = ProjectTemplateBinding::new(
                request.project_id.clone(),
                template_id,
                request.binding_type.clone(),
            );

            let mut final_binding = binding;
            final_binding.priority = priority;

            conn.execute(
                "INSERT INTO project_template_bindings (
                    id, project_id, template_id, binding_name, description, priority,
                    is_active, binding_type, binding_status, metadata, created_at, updated_at
                ) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)",
                rusqlite::params![
                    &final_binding.id,
                    &final_binding.project_id,
                    &final_binding.template_id,
                    &final_binding.binding_name,
                    &final_binding.description,
                    final_binding.priority as i32,
                    final_binding.is_active as i32,
                    &serde_json::to_string(&final_binding.binding_type).unwrap(),
                    &serde_json::to_string(&final_binding.binding_status).unwrap(),
                    &final_binding.metadata,
                    &final_binding.created_at.to_rfc3339(),
                    &final_binding.updated_at.to_rfc3339(),
                ],
            )?;

            bindings.push(final_binding);
            priority += 1;
        }

        Ok(bindings)
    }

    /// 批量删除项目-模板绑定
    pub fn batch_delete(&self, request: BatchDeleteProjectTemplateBindingRequest) -> Result<u32> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        let mut deleted_count = 0;

        for binding_id in request.binding_ids {
            let rows_affected = conn.execute(
                "DELETE FROM project_template_bindings WHERE id = ?1",
                [&binding_id],
            )?;
            deleted_count += rows_affected;
        }

        Ok(deleted_count as u32)
    }

    /// 检查绑定是否存在
    pub fn exists(&self, project_id: &str, template_id: &str) -> Result<bool> {
        let conn = self.database.get_connection();
        let conn = conn.lock().unwrap();
        
        let mut stmt = conn.prepare(
            "SELECT COUNT(*) FROM project_template_bindings WHERE project_id = ?1 AND template_id = ?2"
        )?;

        let count: i64 = stmt.query_row([project_id, template_id], |row| row.get(0))?;
        Ok(count > 0)
    }

    /// 将数据库行转换为绑定实体
    fn row_to_binding(&self, row: &Row) -> Result<ProjectTemplateBinding> {
        let binding_type_str: String = row.get("binding_type")?;
        let binding_status_str: String = row.get("binding_status")?;
        let created_at_str: String = row.get("created_at")?;
        let updated_at_str: String = row.get("updated_at")?;

        Ok(ProjectTemplateBinding {
            id: row.get("id")?,
            project_id: row.get("project_id")?,
            template_id: row.get("template_id")?,
            binding_name: row.get("binding_name")?,
            description: row.get("description")?,
            priority: row.get::<_, i32>("priority")? as u32,
            is_active: row.get::<_, i32>("is_active")? != 0,
            binding_type: serde_json::from_str(&binding_type_str).unwrap_or(BindingType::Primary),
            binding_status: serde_json::from_str(&binding_status_str).unwrap_or(BindingStatus::Active),
            metadata: row.get("metadata")?,
            created_at: DateTime::parse_from_rfc3339(&created_at_str).unwrap().with_timezone(&Utc),
            updated_at: DateTime::parse_from_rfc3339(&updated_at_str).unwrap().with_timezone(&Utc),
        })
    }
}
