//
// Copyright (c) 2025-2026 rustmailer.com (https://rustmailer.com)
//
// This file is part of the Bichon Email Archiving Project
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


use std::process;

use console::style;
use dialoguer::{theme::ColorfulTheme, Select};
use reqwest::Client;

use crate::modules::{
    account::payload::MinimalAccount,
    cli::BichonCtlConfig,
    users::{permissions::Permission, view::UserView},
};

pub async fn verify_user_and_get_account(config: &BichonCtlConfig, theme: &ColorfulTheme) -> u64 {
    let client = Client::new();
    let url = format!("{}/api/v1/current-user", config.base_url);

    let response = match client
        .get(&url)
        .header("Authorization", format!("Bearer {}", config.api_token))
        .send()
        .await
    {
        Ok(res) => res,
        Err(e) => {
            eprintln!(
                "\n{} {}",
                style("✘ Network Error:").red().bold(),
                "Could not connect to Bichon service."
            );
            eprintln!("{} {}", style("Details:").dim(), e);
            eprintln!(
                "\n{} Please check if the Base URL is correct and the server is running.",
                style("Tip:").cyan()
            );
            process::exit(1);
        }
    };

    if !response.status().is_success() {
        let status = response.status();
        let error_body = response
            .text()
            .await
            .unwrap_or_else(|_| "No error detail provided".to_string());

        eprintln!(
            "\n{} Server returned an error (Status: {})",
            style("✘ API Error:").red().bold(),
            style(status).yellow()
        );

        if status == 401 {
            eprintln!(
                "{} Your API Token seems to be invalid or expired.",
                style("Context:").dim()
            );
        } else if status == 404 {
            eprintln!(
                "{} The endpoint was not found. Please check your Base URL.",
                style("Context:").dim()
            );
        }

        eprintln!("{} {}", style("Response:").dim(), error_body);
        process::exit(1);
    }

    let user: UserView = response.json().await.expect("Failed to parse user data");
    println!("Welcome, {}!", style(&user.username).cyan());

    let account_list_url = format!(
        "{}/api/v1/minimal-account-list?only_nosync=true",
        config.base_url
    );
    let acc_response = client
        .get(&account_list_url)
        .header("Authorization", format!("Bearer {}", config.api_token))
        .send()
        .await
        .expect("Failed to fetch account list");

    if !acc_response.status().is_success() {
        panic!(
            "Failed to retrieve accounts. Status: {}",
            acc_response.status()
        );
    }

    let accounts: Vec<MinimalAccount> = acc_response
        .json()
        .await
        .expect("Failed to parse minimal account list");

    if accounts.is_empty() {
        println!(
            "\n{}",
            style("Error: No 'nosync' accounts found.").red().bold()
        );
        println!(
            "{}",
            style("Mail import is only supported for 'nosync' type accounts.").dim()
        );
        println!(
            "Please create a new {} account in the Bichon web interface first.",
            style("Nosync").bold().yellow()
        );
        process::exit(1);
    }
    let required_permission = Permission::DATA_IMPORT_BATCH;
    let mut selectable_accounts = Vec::new();
    let mut options = Vec::new();

    for acc in accounts {
        let has_permission = if let Some(perms) = user.account_permissions.get(&acc.id) {
            perms.iter().any(|p| p == required_permission)
        } else {
            user.global_permissions
                .iter()
                .any(|p| p == Permission::DATA_MANAGE_ALL || p == Permission::ROOT)
        };

        let status_prefix = if has_permission {
            style(" [READY] ").green()
        } else {
            style(" [NO PERMISSION] ").red()
        };

        options.push(format!(
            "{}{} - {}",
            status_prefix,
            style(&acc.email).bold(),
            style(format!("ID: {}", acc.id)).dim()
        ));

        selectable_accounts.push((acc, has_permission));
    }

    let selection = Select::with_theme(theme)
        .with_prompt("Select the target account for import")
        .items(&options)
        .default(0)
        .max_length(10)
        .interact()
        .unwrap();

    let (selected_acc, can_import) = &selectable_accounts[selection];

    if !*can_import {
        eprintln!(
            "\n{} You do not have '{}' permission for account {}.",
            style("✘ Permission Denied:").red().bold(),
            style(required_permission).yellow(),
            style(&selected_acc.email).cyan()
        );
        eprintln!(
            "{} Please contact your administrator to upgrade your role for this account.",
            style("Tip:").dim()
        );
        process::exit(1);
    }

    println!(
        "{} Targeting account: {}",
        style("✔").green(),
        style(&selected_acc.email).cyan().bold()
    );

    selected_acc.id
}
