use crate::{ApiResponse, error::ApiError};
use actix_web::{HttpResponse, Result, web};
use service::AppService;
use service::error::AppError;
use service::project::activity::{ActivityLogListResponse, ActivityLogParams, ActivityLogResponse};
use session::Session;

#[derive(serde::Deserialize, utoipa::IntoParams)]
pub struct ActivityQuery {
    pub page: Option<u64>,
    pub per_page: Option<u64>,
    pub event_type: Option<String>,
    pub start_date: Option<String>,
    pub end_date: Option<String>,
}

impl From<ActivityQuery> for service::project::activity::ActivityParams {
    fn from(q: ActivityQuery) -> Self {
        service::project::activity::ActivityParams {
            event_type: q.event_type,
            start_date: q.start_date,
            end_date: q.end_date,
        }
    }
}

#[utoipa::path(
    get,
    path = "/api/projects/{project_name}/activities",
    params(
        ("project_name" = String, Path),
        ("page" = Option<u64>, Query),
        ("per_page" = Option<u64>, Query),
        ("event_type" = Option<String>, Query),
        ("start_date" = Option<String>, Query, description = "ISO 8601 datetime, e.g. 2025-01-01T00:00:00Z"),
        ("end_date" = Option<String>, Query, description = "ISO 8601 datetime, e.g. 2025-12-31T23:59:59Z"),
    ),
    responses(
        (status = 200, description = "List project activities", body = ApiResponse<ActivityLogListResponse>),
        (status = 401, description = "Unauthorized"),
        (status = 403, description = "Forbidden — no access to this project"),
        (status = 404, description = "Project not found"),
    ),
    tag = "Project"
)]
pub async fn project_activities(
    service: web::Data<AppService>,
    session: Session,
    path: web::Path<String>,
    query: web::Query<ActivityQuery>,
) -> Result<HttpResponse, ApiError> {
    let project_name = path.into_inner();
    let page = query.page;
    let per_page = query.per_page;
    let params = service::project::activity::ActivityParams::from(query.into_inner());
    let resp = service
        .project_get_activities(project_name, page, per_page, Some(params), &session)
        .await?;
    Ok(ApiResponse::ok(resp).to_response())
}

#[utoipa::path(
    post,
    path = "/api/projects/{project_name}/activities",
    params(("project_name" = String, Path)),
    request_body = ActivityLogParams,
    responses(
        (status = 200, description = "Activity logged", body = ApiResponse<ActivityLogResponse>),
        (status = 401, description = "Unauthorized"),
        (status = 404, description = "Project not found"),
    ),
    tag = "Project"
)]
pub async fn project_log_activity(
    service: web::Data<AppService>,
    session: Session,
    path: web::Path<String>,
    body: web::Json<ActivityLogParams>,
) -> Result<HttpResponse, ApiError> {
    let project_name = path.into_inner();
    let _project = service.utils_find_project_by_name(project_name).await?;
    let user_uid = session.user().ok_or(AppError::Unauthorized)?;

    let resp = service
        .project_log_activity(_project.id, body.repo_id, user_uid, body.into_inner())
        .await?;
    Ok(ApiResponse::ok(resp).to_response())
}
