use crate::core::time::{iso_to_ms_opt_strict, iso_to_ms_strict, now_ms};
use crate::gitlab::types::GitLabMergeRequest;

#[derive(Debug, Clone)]
pub struct NormalizedMergeRequest {
    pub gitlab_id: i64,
    pub project_id: i64,
    pub iid: i64,
    pub title: String,
    pub description: Option<String>,
    pub state: String,
    pub draft: bool,
    pub author_username: String,
    pub source_branch: String,
    pub target_branch: String,
    pub head_sha: Option<String>,
    pub references_short: Option<String>,
    pub references_full: Option<String>,
    pub detailed_merge_status: Option<String>,
    pub merge_user_username: Option<String>,
    pub created_at: i64,
    pub updated_at: i64,
    pub merged_at: Option<i64>,
    pub closed_at: Option<i64>,
    pub last_seen_at: i64,
    pub web_url: String,
    pub merge_commit_sha: Option<String>,
    pub squash_commit_sha: Option<String>,
}

#[derive(Debug, Clone)]
pub struct MergeRequestWithMetadata {
    pub merge_request: NormalizedMergeRequest,
    pub label_names: Vec<String>,
    pub assignee_usernames: Vec<String>,
    pub reviewer_usernames: Vec<String>,
}

pub fn transform_merge_request(
    gitlab_mr: &GitLabMergeRequest,
    local_project_id: i64,
) -> Result<MergeRequestWithMetadata, String> {
    let created_at = iso_to_ms_strict(&gitlab_mr.created_at)?;
    let updated_at = iso_to_ms_strict(&gitlab_mr.updated_at)?;

    let merged_at = iso_to_ms_opt_strict(&gitlab_mr.merged_at)?;
    let closed_at = iso_to_ms_opt_strict(&gitlab_mr.closed_at)?;

    let is_draft = gitlab_mr.draft || gitlab_mr.work_in_progress;

    let detailed_merge_status = gitlab_mr
        .detailed_merge_status
        .clone()
        .or_else(|| gitlab_mr.merge_status_legacy.clone());

    let merge_user_username = gitlab_mr
        .merge_user
        .as_ref()
        .map(|u| u.username.clone())
        .or_else(|| gitlab_mr.merged_by.as_ref().map(|u| u.username.clone()));

    let (references_short, references_full) = gitlab_mr
        .references
        .as_ref()
        .map(|r| (Some(r.short.clone()), Some(r.full.clone())))
        .unwrap_or((None, None));

    let head_sha = gitlab_mr.sha.clone();

    let assignee_usernames: Vec<String> = gitlab_mr
        .assignees
        .iter()
        .map(|a| a.username.clone())
        .collect();

    let reviewer_usernames: Vec<String> = gitlab_mr
        .reviewers
        .iter()
        .map(|r| r.username.clone())
        .collect();

    Ok(MergeRequestWithMetadata {
        merge_request: NormalizedMergeRequest {
            gitlab_id: gitlab_mr.id,
            project_id: local_project_id,
            iid: gitlab_mr.iid,
            title: gitlab_mr.title.clone(),
            description: gitlab_mr.description.clone(),
            state: gitlab_mr.state.clone(),
            draft: is_draft,
            author_username: gitlab_mr.author.username.clone(),
            source_branch: gitlab_mr.source_branch.clone(),
            target_branch: gitlab_mr.target_branch.clone(),
            head_sha,
            references_short,
            references_full,
            detailed_merge_status,
            merge_user_username,
            created_at,
            updated_at,
            merged_at,
            closed_at,
            last_seen_at: now_ms(),
            web_url: gitlab_mr.web_url.clone(),
            merge_commit_sha: gitlab_mr.merge_commit_sha.clone(),
            squash_commit_sha: gitlab_mr.squash_commit_sha.clone(),
        },
        label_names: gitlab_mr.labels.clone(),
        assignee_usernames,
        reviewer_usernames,
    })
}
