use crate::extract::Extractor;
use crate::EternaltwinSystem;
use axum::body::Body;
use axum::http::StatusCode;
use axum::response::{IntoResponse, Redirect, Response};
use axum::routing::post;
use axum::{Extension, Form, Router};
use eternaltwin_core::auth::AuthContext;
use eternaltwin_core::user::{LinkToDinoparcOptions, LinkToHammerfestOptions};
use thiserror::Error;

pub fn router() -> Router<(), Body> {
  Router::new()
    .route("/dinoparc", post(link_to_dinoparc))
    .route("/hammerfest", post(link_to_hammerfest))
  // .route("/twinoid", post(link_to_twinoid))
}

#[derive(Debug, Error)]
enum LinkToDinoparcError {
  #[error("inner error")]
  Inner(#[from] eternaltwin_services::user::LinkToDinoparcError),
}

impl IntoResponse for LinkToDinoparcError {
  fn into_response(self) -> Response {
    let (code, msg) = match self {
      Self::Inner(_) => (StatusCode::INTERNAL_SERVER_ERROR, "internal server error".to_string()),
    };
    (code, msg).into_response()
  }
}

async fn link_to_dinoparc(
  Extension(api): Extension<EternaltwinSystem>,
  acx: Extractor<AuthContext>,
  Form(body): Form<LinkToDinoparcOptions>,
) -> Result<Redirect, LinkToDinoparcError> {
  match api.user.as_ref().link_to_dinoparc(acx.value(), body).await {
    Ok(_) => Ok(Redirect::to("/settings")),
    Err(_) => Ok(Redirect::to("/settings")),
  }
}

#[derive(Debug, Error)]
enum LinkToHammerfestError {
  #[error("inner error")]
  Inner(#[from] eternaltwin_services::user::LinkToHammerfestError),
}

impl IntoResponse for LinkToHammerfestError {
  fn into_response(self) -> Response {
    let (code, msg) = match self {
      Self::Inner(_) => (StatusCode::INTERNAL_SERVER_ERROR, "internal server error".to_string()),
    };
    (code, msg).into_response()
  }
}

async fn link_to_hammerfest(
  Extension(api): Extension<EternaltwinSystem>,
  acx: Extractor<AuthContext>,
  Form(body): Form<LinkToHammerfestOptions>,
) -> Result<Redirect, LinkToHammerfestError> {
  match api.user.as_ref().link_to_hammerfest(acx.value(), body).await {
    Ok(_) => Ok(Redirect::to("/settings")),
    Err(_) => Ok(Redirect::to("/settings")),
  }
}

// #[derive(Debug, Error)]
// enum LinkToTwinoidError {
//   #[error("inner error")]
//   Inner(#[from] AnyError),
// }
//
// impl IntoResponse for LinkToTwinoidError {
//   fn into_response(self) -> Response {
//     let (code, msg) = match self {
//       Self::Inner(_) => (StatusCode::INTERNAL_SERVER_ERROR, "internal server error".to_string()),
//     };
//     (code, msg).into_response()
//   }
// }
//
// async fn link_to_twinoid(
//   Extension(api): Extension<EternaltwinSystem>,
//   acx: Extractor<AuthContext>,
// ) -> Result<Redirect, LinkToTwinoidError> {
//   let acx = match acx.value() {
//     AuthContext::User(acx) => acx,
//     _ => return Ok(Redirect::to("/login")),
//   };
//   let authorization_uri = api
//     .auth
//     .as_ref()
//     .request_twinoid_auth(EtwinOauthStateAction::Link { user_id: acx.user.id })
//     .await?;
//   Ok(Redirect::to(authorization_uri.as_str()))
// }
