use actix_web::{
    error::{ErrorBadRequest, ErrorInternalServerError},
    web, HttpResponse, Responder,
};
use argon2::{Argon2, PasswordHash, PasswordVerifier};
use jsonwebtoken::EncodingKey;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
use serde::Deserialize;

use crate::{auth::create_jwt, AppState};

#[derive(Deserialize)]
pub struct LoginRequest {
    email: String,
    password: String,
}

pub struct AuthController;

impl AuthController {
    pub async fn login(
        state: web::Data<AppState>,
        login: web::Json<LoginRequest>,
    ) -> actix_web::Result<impl Responder> {
        let db = &state.db;
        let jwt_secret = &state.secret;
        let login = login.into_inner();

        let user = entity::user::Entity::find()
            .filter(entity::user::Column::Email.eq(login.email))
            .one(db)
            .await
            .map_err(ErrorInternalServerError)?
            .ok_or(ErrorBadRequest("Login Failed"))?;

        let argon2 = Argon2::default();
        let parsed_hash = PasswordHash::new(&user.hash).map_err(ErrorInternalServerError)?;
        argon2
            .verify_password(login.password.as_bytes(), &parsed_hash)
            .map_err(ErrorBadRequest)?;

        let jwt = create_jwt(user, &EncodingKey::from_secret(jwt_secret.as_bytes()))
            .map_err(ErrorInternalServerError)?;
        Ok(HttpResponse::Ok().body(jwt))
    }
}
