use actix_web::{get, web, HttpResponse};
use serde::{Deserialize, Serialize};

use sqlx::{Pool, Sqlite};

use crate::db::DbRelay;

use crate::handlers::errors::ApiError;
use crate::models::Relay;

#[derive(Debug, Serialize, Deserialize)]
pub struct RequestRelay {
	name: String,
	tags: Vec<String>,
}

#[get("/api/v1/relays")]
pub async fn index(pool: web::Data<Pool<Sqlite>>) -> Result<HttpResponse, ApiError> {
	let mut pool_conn = pool.acquire().await?;

	let relays = DbRelay::get_all(&mut pool_conn).await?;

	let return_relays: Vec<Relay> = relays
		.into_iter()
		.map(|s| Relay::from_db_relay(s, &mut pool_conn))
		.collect();

	Ok(HttpResponse::Ok().json(return_relays))
}

//#[get("/api/v1/tags/tag/{tag}")]
//pub async fn tagged(
//	pool: web::Data<Pool<Sqlite>>,
//	path: web::Path<(String,)>,
//) -> Result<HttpResponse, ApiError> {
//	let mut pool_conn = pool.acquire().await?;
//
//	let (tag,) = path.into_inner();
//	let tag_db = Tag::get_by_tag(&mut pool_conn, &tag).await?;
//
//	let relays = Relay::get_by_tag(&mut pool_conn, &tag_db).await?;
//
//	let return_relays: Vec<ReturnRelay> =
//		relays.into_iter().map(|s| ReturnRelay::from_relay(s, &mut pool_conn)).collect();
//
//	Ok(HttpResponse::Ok().json(return_relays))
//}
//
//#[get("/api/v1/tags/{relay_id}")]
//pub async fn show(
//	pool: web::Data<Pool<Sqlite>>,
//	path: web::Path<(String,)>,
//) -> Result<HttpResponse, ApiError> {
//	let mut pool_conn = pool.acquire().await?;
//
//	let (relay_uid,) = path.into_inner();
//	let uid = RelayUid::try_from(relay_uid.as_str()).or(Err(ApiError::BadUid))?;
//
//	let relay = Relay::get_by_uid(&mut pool_conn, &uid).await?;
//
//	let return_relay = ReturnRelay::from_relay(relay, &mut pool_conn);
//	Ok(HttpResponse::Ok().json(return_relay))
//}
//
//#[post("/api/v1/tags")]
//pub async fn add(
//	pool: web::Data<Pool<Sqlite>>,
//	data: web::Json<RequestRelay>,
//) -> Result<HttpResponse, ApiError> {
//	let mut pool_conn = pool.acquire().await?;
//
//	let new_relay = Relay::create(&mut pool_conn, &data.name, &data.periods).await?;
//
//	new_relay
//		.set_tags(&mut pool_conn, data.tags.as_slice())
//		.await?;
//
//	let return_relay = ReturnRelay::from_relay(new_relay, &mut pool_conn);
//	Ok(HttpResponse::Created().json(return_relay))
//}
//
//async fn add_list_single(
//	conn: &mut PoolConnection<Sqlite>,
//	request_relay: &RequestRelay,
//) -> Result<Relay, DatabaseError> {
//	let new_relay =
//		Relay::create(conn, &request_relay.name, &request_relay.periods).await?;
//
//	new_relay
//		.set_tags(conn, request_relay.tags.as_slice())
//		.await?;
//
//	Ok(new_relay)
//}
//
//#[post("/api/v1/tags/list")]
//pub async fn add_list(
//	pool: web::Data<Pool<Sqlite>>,
//	data: web::Json<Vec<RequestRelay>>,
//) -> Result<HttpResponse, ApiError> {
//	let mut pool_conn = pool.acquire().await?;
//
//	let result: Vec<Result<Relay, DatabaseError>> = data
//		.as_slice()
//		.iter()
//		.map(|request_relay| {
//			futures::executor::block_on(add_list_single(&mut pool_conn, request_relay))
//		})
//		.collect();
//
//	let mut return_relays: Vec<ReturnRelay> = Vec::new();
//	for relay in result {
//		match relay {
//			Ok(relay) => return_relays.push(ReturnRelay::from_relay(relay, &mut pool_conn)),
//			Err(e) => return Ok(HttpResponse::from(e)),
//		}
//	}
//	Ok(HttpResponse::Created().json(return_relays))
//}
//
//#[put("/api/v1/tags/{relay_id}")]
//pub async fn update(
//	pool: web::Data<Pool<Sqlite>>,
//	path: web::Path<(String,)>,
//	data: web::Json<RequestRelay>,
//) -> Result<HttpResponse, ApiError> {
//	let mut pool_conn = pool.acquire().await?;
//
//	let (relay_uid,) = path.into_inner();
//	let uid = RelayUid::try_from(relay_uid.as_str()).or(Err(ApiError::BadUid))?;
//
//	let relay = Relay::get_by_uid(&mut pool_conn, &uid).await?;
//
//	let relay = relay
//		.update(&mut pool_conn, data.name.as_str(), &data.periods)
//		.await?;
//
//	relay
//		.set_tags(&mut pool_conn, data.tags.as_slice())
//		.await?;
//
//	let return_relay = ReturnRelay::from_relay(relay, &mut pool_conn);
//	Ok(HttpResponse::Ok().json(return_relay))
//}
//
//#[delete("/api/v1/tags/{relay_id}")]
//pub async fn delete(
//	pool: web::Data<Pool<Sqlite>>,
//	path: web::Path<(String,)>,
//) -> Result<HttpResponse, ApiError> {
//	let mut pool_conn = pool.acquire().await?;
//
//	let (relay_uid,) = path.into_inner();
//	let uid = RelayUid::try_from(relay_uid.as_str()).or(Err(ApiError::BadUid))?;
//
//	match uid {
//		RelayUid::Off => Err(ApiError::ProtectedRelay),
//		RelayUid::On => Err(ApiError::ProtectedRelay),
//		RelayUid::Any(_) => {
//			Relay::delete_by_uid(&mut pool_conn, uid).await?;
//			Ok(HttpResponse::Ok().json("relay got deleted"))
//		}
//	}
//}