use diesel::dsl::sql;
use diesel::prelude::*;


use crate::db::errors::DatabaseError;
use crate::db::{get_connection, schema};
use crate::db::models::*;
use crate::db::schema::tags::dsl::tags;
use crate::db::schema::junction_tag::dsl::junction_tag;


pub fn create_tag(new_tag: &str) -> Result<Tag, DatabaseError> {
    let connection = get_connection();

    let new_tag = NewTag {
        tag: new_tag,
    };

    diesel::insert_into(tags)
        .values(&new_tag)
        .execute(&connection)
        .map_err(DatabaseError::InsertError)?;

    let result = tags
        .find(sql("last_insert_rowid()"))
        .get_result::<Tag>(&connection)
        .or(Err(DatabaseError::InsertGetError))?;

    Ok(result)
}

pub fn get_tag(target_tag: &str) -> Result<Tag, DatabaseError> {
    let connection = get_connection();

    let result = tags
        .filter(schema::tags::tag.eq(target_tag))
        .first::<Tag>(&connection)
        .or(Err(DatabaseError::NotFound))?;

    Ok(result)
}

pub fn create_junction_tag(target_tag: Tag, target_relay: Option<&Relay>, target_schedule: Option<&Schedule>) -> Result<JunctionTag, DatabaseError> {
    let connection = get_connection();

    let new_junction_tag = NewJunctionTag {
        relay_id: target_relay.map(|r| r.id),
        schedule_id: target_schedule.map(|s| s.id),
        tag_id: target_tag.id
    };

    diesel::insert_into(junction_tag)
        .values(&new_junction_tag)
        .execute(&connection)
        .map_err(DatabaseError::InsertError)?;

    let result = junction_tag
        .find(sql("last_insert_rowid()"))
        .get_result::<JunctionTag>(&connection)
        .or(Err(DatabaseError::InsertGetError))?;

    Ok(result)
}