use sqlx::PgPool;
use uuid::Uuid;

use crate::{
    error::{ApiError, Result},
    models::{Bulletin, CreateBulletinRequest},
    utils::{
        sanitize::strip_html_tags,
        db_operations::{DbOperations, BulletinOperations},
    },
};

pub async fn list(
    pool: &PgPool,
    page: i32,
    per_page: i64,
    active_only: bool,
) -> Result<(Vec<Bulletin>, i64)> {
    let offset = ((page - 1) as i64) * per_page;
    
    // Use shared database operations
    BulletinOperations::list_paginated(pool, offset, per_page, active_only).await
}

pub async fn get_current(pool: &PgPool) -> Result<Option<Bulletin>> {
    // Use shared database operations
    BulletinOperations::get_current(pool).await
}

pub async fn get_by_id(pool: &PgPool, id: &Uuid) -> Result<Option<Bulletin>> {
    // Use shared database operations
    DbOperations::get_by_id(pool, "bulletins", id).await
}

pub async fn get_by_date(pool: &PgPool, date: chrono::NaiveDate) -> Result<Option<Bulletin>> {
    let bulletin = sqlx::query_as!(
        Bulletin,
        "SELECT id, title, date, url, pdf_url, is_active, pdf_file, sabbath_school, 
                divine_worship, scripture_reading, sunset, cover_image, pdf_path, 
                created_at, updated_at
         FROM bulletins 
         WHERE date = $1 AND is_active = true
         ORDER BY created_at DESC
         LIMIT 1",
        date
    )
    .fetch_optional(pool)
    .await
    .map_err(ApiError::DatabaseError)?;
    
    Ok(bulletin)
}

pub async fn create(pool: &PgPool, req: CreateBulletinRequest) -> Result<Bulletin> {
    let bulletin = sqlx::query_as!(
        Bulletin,
        "INSERT INTO bulletins (title, date, url, cover_image, sabbath_school, divine_worship, scripture_reading, sunset, is_active) 
         VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) 
         RETURNING id, title, date, url, pdf_url, is_active, pdf_file, sabbath_school, divine_worship, 
                   scripture_reading, sunset, cover_image, pdf_path, created_at, updated_at",
        strip_html_tags(&req.title),
        req.date,
        req.url.as_ref().map(|s| strip_html_tags(s)),
        req.cover_image.as_ref().map(|s| strip_html_tags(s)),
        req.sabbath_school.as_ref().map(|s| strip_html_tags(s)),
        req.divine_worship.as_ref().map(|s| strip_html_tags(s)),
        req.scripture_reading.as_ref().map(|s| strip_html_tags(s)),
        req.sunset.as_ref().map(|s| strip_html_tags(s)),
        req.is_active.unwrap_or(true)
    )
    .fetch_one(pool)
    .await?;

    Ok(bulletin)
}

pub async fn update(
    pool: &PgPool,
    id: &Uuid,
    req: CreateBulletinRequest,
) -> Result<Option<Bulletin>> {
    let bulletin = sqlx::query_as!(
        Bulletin,
        "UPDATE bulletins 
         SET title = $1, date = $2, url = $3, cover_image = $4, sabbath_school = $5, divine_worship = $6, 
             scripture_reading = $7, sunset = $8, is_active = $9, updated_at = NOW()
         WHERE id = $10 
         RETURNING id, title, date, url, pdf_url, is_active, pdf_file, sabbath_school, divine_worship, 
                   scripture_reading, sunset, cover_image, pdf_path, created_at, updated_at",
        strip_html_tags(&req.title),
        req.date,
        req.url.as_ref().map(|s| strip_html_tags(s)),
        req.cover_image.as_ref().map(|s| strip_html_tags(s)),
        req.sabbath_school.as_ref().map(|s| strip_html_tags(s)),
        req.divine_worship.as_ref().map(|s| strip_html_tags(s)),
        req.scripture_reading.as_ref().map(|s| strip_html_tags(s)),
        req.sunset.as_ref().map(|s| strip_html_tags(s)),
        req.is_active.unwrap_or(true),
        id
    )
    .fetch_optional(pool)
    .await?;

    Ok(bulletin)
}

pub async fn delete(pool: &PgPool, id: &Uuid) -> Result<()> {
    let result = sqlx::query!("DELETE FROM bulletins WHERE id = $1", id)
        .execute(pool)
        .await?;

    if result.rows_affected() == 0 {
        return Err(ApiError::NotFound("Bulletin not found".to_string()));
    }

    Ok(())
}
