use ngoni::{ses::send_email, stripe::CHECKOUT_SESSION_ID, stripe::Stripe};

#[tokio::main]
async fn main() {
	dotenvy::from_filename("secret/.env").ok();
	let secret_key = std::env::var("STRIPE_SECRET_KEY").unwrap_or_default();
	let server = Example {
		stripe: Stripe::new(secret_key),
	};
	let port: u16 = std::env::var("PORT")
		.unwrap_or("8000".to_string())
		.parse()
		.expect("PORT should be integer");
	out::print_axum_router(port);
	let app = out::axum_router(server);
	let listener = tokio::net::TcpListener::bind(format!("0.0.0.0:{port}"))
		.await
		.unwrap();
	println!("serve on http://localhost:{port}/");
	axum::serve(listener, app.clone())
		.with_graceful_shutdown(async move {
			tokio::signal::ctrl_c().await.unwrap();
		})
		.await
		.unwrap();
}
struct Example {
	stripe: Stripe,
}
impl out::ApiInterface for Example {
	async fn ngoni_email(&self, req: out::NgoniEmailRequest) -> out::NgoniEmailResponse {
		let from = "noreply@surfic.com"; // SES で Verify 済み
		let to = &req.body.to;
		let subject = &req.body.subject;
		let body = &req.body.body;

		let result = send_email(from, to, subject, body).await;
		match result {
			Ok(_) => out::NgoniEmailResponse::Status204,
			Err(e) => out::NgoniEmailResponse::Status400(e.to_string()),
		}
	}
	async fn ngoni_payment(&self, req: out::NgoniPaymentRequest) -> out::NgoniPaymentResponse {
		let origin = out::origin_from_request(&req.request).unwrap_or_default();
		// Checkout Session を作る
		let session = self
			.stripe
			.create_payment_session(
				None,
				None,
				vec![
					ngoni::stripe::StripeOrder {
						name: "テスト10円ガム".to_string(),
						id: "019bb2ff-fa86-738b-8adc-b7f0354a23c6".to_string(),
						currency: ngoni::stripe::Currency::JPY,
						price: 10,
						quantity: 2,
					},
					ngoni::stripe::StripeOrder {
						name: "テストガリガリ君".to_string(),
						id: "019bb2ff-fa86-738b-8adc-b7f0354a23c6".to_string(),
						currency: ngoni::stripe::Currency::JPY,
						price: 100,
						quantity: 1,
					},
				],
				&format!("{origin}/checkout?session_id={CHECKOUT_SESSION_ID}"),
				&format!("{origin}/cancel?session_id={CHECKOUT_SESSION_ID}"),
			)
			.await;
		match session {
			Ok(session) => {
				out::NgoniPaymentResponse::Raw(
					axum::response::Response::builder()
						.status(axum::http::StatusCode::TEMPORARY_REDIRECT)
						.header(axum::http::header::LOCATION, session.url.unwrap()) // リダイレクト先のURLを Location ヘッダーに設定
						.body(axum::body::Body::empty()) //				// ボディがないため、空のボディを設定してビルド
						.unwrap(),
				)
			}
			Err(e) => out::NgoniPaymentResponse::Status400(e.to_string()),
		}
	}
	/*
	async fn ngoni_subscription(
		&self,
		req: out::NgoniSubscriptionRequest,
	) -> out::NgoniSubscriptionResponse {
		let product = self.stripe.create_product("100円/月").await.unwrap();
		let price_usd = self
			.stripe
			.create_price(
				&product.id,
				100,
				ngoni::stripe::Currency::JPY,
				Some(ngoni::stripe::IntervalWithOptions {
					interval: ngoni::stripe::Interval::Month,
					..Default::default()
				}),
			)
			.await
			.unwrap();
		let origin = out::origin_from_request(&req.request).unwrap_or_default();
		// Checkout Session を作る
		let session = self
			.stripe
			.create_checkout_session(
				&price_usd.id,
				ngoni::stripe::SessionMode::Subscription,
				None,
				&format!("{origin}/checkout?session_id={}", CHECKOUT_SESSION_ID),
				&format!("{origin}/cancel?session_id={}", CHECKOUT_SESSION_ID),
			)
			.await;
		match session {
			Ok(session) => {
				out::NgoniSubscriptionResponse::Raw(
					axum::response::Response::builder()
						.status(axum::http::StatusCode::TEMPORARY_REDIRECT)
						.header(axum::http::header::LOCATION, session.url.unwrap()) // リダイレクト先のURLを Location ヘッダーに設定
						.body(axum::body::Body::empty()) //						// ボディがないため、空のボディを設定してビルド
						.unwrap(),
				)
			}
			Err(e) => out::NgoniSubscriptionResponse::Status400(e.to_string()),
		}
	}
	 */
	async fn ngoni_checkout(&self, _req: out::NgoniCheckoutRequest) -> out::NgoniCheckoutResponse {
		//let session_id = req.body.session_id;
		//let session = self.stripe.get_checkout_session(&session_id).await.unwrap();
		out::NgoniCheckoutResponse::Status204
	}
}

#[allow(dead_code, unused_variables, unused_imports)]
mod out {
	include!("./out.txt");
}
