use leptos::prelude::*;
use serde::{Deserialize, Serialize};
use rustelo_core_lib::auth::{Setup2FARequest, Setup2FAResponse, TwoFactorStatus, Verify2FARequest};

use crate::utils::api_request;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ApiResponse<T> {
  pub success: bool,
  pub data: Option<T>,
  pub message: Option<String>,
  pub errors: Option<Vec<String>>,
}

#[derive(Debug, Clone)]
enum TwoFactorSetupState {
  Loading,
  Error,
  NotEnabled,
  PendingVerification(Setup2FAResponse),
  Enabled(TwoFactorStatus),
}

#[component]
pub fn TwoFactorSetup() -> impl IntoView {
  let (setup_state, set_setup_state) = signal(TwoFactorSetupState::Loading);
  let (password, set_password) = signal(String::new());
  let (verification_code, set_verification_code) = signal(String::new());
  let (error_message, set_error_message) = signal(Option::<String>::None);
  let (success_message, set_success_message) = signal(Option::<String>::None);

  // Load 2FA status on component mount
  let load_2fa_status = Action::new(move |_: &()| async move {
    match api_request::<(), ApiResponse<TwoFactorStatus>>("/api/auth/2fa/status", "GET", None)
      .await
    {
      Ok(response) => {
        if response.success {
          if let Some(status) = response.data {
            if status.is_enabled {
              set_setup_state.set(TwoFactorSetupState::Enabled(status));
            } else {
              set_setup_state.set(TwoFactorSetupState::NotEnabled);
            }
          }
        } else {
          set_error_message.set(Some(
            response
              .message
              .unwrap_or_else(|| "Failed to load 2FA status".to_string()),
          ));
          set_setup_state.set(TwoFactorSetupState::Error);
        }
      }
      Err(e) => {
        set_error_message.set(Some(format!("Failed to load 2FA status: {}", e)));
        set_setup_state.set(TwoFactorSetupState::Error);
      }
    }
  });

  // Setup 2FA action
  let setup_2fa_action = Action::new(move |password: &String| {
    let password = password.clone();
    async move {
      let request = Setup2FARequest { password };
      match api_request::<Setup2FARequest, ApiResponse<Setup2FAResponse>>(
        "/api/auth/2fa/setup",
        "POST",
        Some(request),
      )
      .await
      {
        Ok(response) => {
          if response.success {
            if let Some(setup_response) = response.data {
              set_setup_state
                .set(TwoFactorSetupState::PendingVerification(setup_response));
              set_success_message.set(response.message);
              set_error_message.set(None);
            }
          } else {
            set_error_message.set(response.message);
          }
        }
        Err(e) => {
          set_error_message.set(Some(format!("Failed to setup 2FA: {}", e)));
        }
      }
    }
  });

  // Verify 2FA setup action
  let verify_2fa_action = Action::new(move |code: &String| {
    let code = code.clone();
    async move {
      let request = Verify2FARequest { code };
      match api_request::<Verify2FARequest, ApiResponse<()>>(
        "/api/auth/2fa/verify",
        "POST",
        Some(request),
      )
      .await
      {
        Ok(response) => {
          if response.success {
            set_success_message.set(Some("2FA enabled successfully!".to_string()));
            set_error_message.set(None);
            load_2fa_status.dispatch(());
          } else {
            set_error_message.set(response.message);
          }
        }
        Err(e) => {
          set_error_message.set(Some(format!("Failed to verify 2FA: {}", e)));
        }
      }
    }
  });

  // Load status on mount
  Effect::new(move |_| {
    load_2fa_status.dispatch(());
  });

  let handle_setup_submit = move |ev: leptos::ev::SubmitEvent| {
    ev.prevent_default();
    if !password.get().is_empty() {
      setup_2fa_action.dispatch(password.get());
    }
  };

  let handle_verify_submit = move |ev: leptos::ev::SubmitEvent| {
    ev.prevent_default();
    if !verification_code.get().is_empty() {
      verify_2fa_action.dispatch(verification_code.get());
    }
  };

  view! {
    <div class="max-w-2xl mx-auto p-ds-6">
      <h1 class="text-3xl font-bold mb-6">"Two-Factor Authentication"</h1>

      // Error message
      {move || {
        if let Some(msg) = error_message.get() {
          view! {
            <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 ds-rounded mb-ds-4">
              {msg}
            </div>
          }.into_any()
        } else {
          view! { <div></div> }.into_any()
        }
      }}

      // Success message
      {move || {
        if let Some(msg) = success_message.get() {
          view! {
            <div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 ds-rounded mb-ds-4">
              {msg}
            </div>
          }.into_any()
        } else {
          view! { <div></div> }.into_any()
        }
      }}

      // Main content based on setup state
      {move || match setup_state.get() {
        TwoFactorSetupState::Loading => view! {
          <div class="text-center py-8">
            <div class="animate-spin ds-rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto"></div>
            <p class="mt-2 ds-text-secondary">"Loading 2FA status..."</p>
          </div>
        }.into_any(),

        TwoFactorSetupState::Error => view! {
          <div class="text-center py-8">
            <p class="ds-text">"Failed to load 2FA status"</p>
            <button
              class="mt-4 px-ds-4 py-ds-2 bg-blue-500 ds-text ds-rounded hover:bg-ds-brand-primary"
              on:click=move |_| load_2fa_status.dispatch(())
            >
              "Retry"
            </button>
          </div>
        }.into_any(),

        TwoFactorSetupState::NotEnabled => view! {
          <div class="bg-blue-50 border border-blue-200 ds-rounded-lg p-ds-6 mb-6">
            <h2 class="ds-heading-4 mb-ds-4">"Enable Two-Factor Authentication"</h2>
            <p class="ds-text-secondary mb-ds-4">
              "Add an extra layer of security to your account by enabling two-factor authentication."
            </p>

            <form on:submit=handle_setup_submit>
              <div class="mb-ds-4">
                <label class="block ds-caption font-medium ds-text-secondary mb-2">
                  "Current Password"
                </label>
                <input
                  type="password"
                  class="w-full px-3 py-2 border ds-border ds-rounded-md"
                  placeholder="Enter your current password"
                  prop:value=password
                  on:input=move |ev| set_password.set(event_target_value(&ev))
                  required
                />
              </div>

              <button
                type="submit"
                class="w-full bg-blue-500 ds-text py-2 px-4 ds-rounded-md"
                disabled=move || setup_2fa_action.pending().get()
              >
                {move || if setup_2fa_action.pending().get() {
                  "Setting up..."
                } else {
                  "Setup 2FA"
                }}
              </button>
            </form>
          </div>
        }.into_any(),

        TwoFactorSetupState::PendingVerification(setup_response) => view! {
          <div class="bg-yellow-50 border border-yellow-200 ds-rounded-lg p-ds-6 mb-6">
            <h2 class="ds-heading-4 mb-ds-4">"Verify Two-Factor Authentication"</h2>

            <div class="mb-6">
              <h3 class="ds-body font-medium mb-2">"Step 1: Scan QR Code"</h3>
              <p class="ds-text-secondary mb-ds-4">
                "Scan this QR code with your authenticator app."
              </p>
              <div class="flex justify-center mb-ds-4">
                <img
                  src=setup_response.qr_code_url.clone()
                  alt="QR Code for 2FA setup"
                  class="border ds-border ds-rounded"
                />
              </div>

              <div class=" p-3 ds-rounded">
                <p class="ds-caption ds-text-secondary mb-2">"Secret:"</p>
                <code class="ds-caption font-mono ds-bg p-ds-2 ds-rounded border">
                  {setup_response.secret.clone()}
                </code>
              </div>
            </div>

            <div class="mb-6">
              <h3 class="ds-body font-medium mb-2">"Step 2: Save Backup Codes"</h3>
              <div class=" p-4 ds-rounded">
                <p class="ds-caption ds-text-secondary mb-2">
                  "Backup codes: " {setup_response.backup_codes.len().to_string()} " codes generated"
                </p>
              </div>
            </div>

            <div class="mb-6">
              <h3 class="ds-body font-medium mb-2">"Step 3: Verify Setup"</h3>
              <form on:submit=handle_verify_submit>
                <div class="mb-ds-4">
                  <input
                    type="text"
                    class="w-full px-3 py-2 border ds-border ds-rounded-md text-center"
                    placeholder="000000"
                    maxlength="6"
                    prop:value=verification_code
                    on:input=move |ev| set_verification_code.set(event_target_value(&ev))
                    required
                  />
                </div>

                <button
                  type="submit"
                  class="w-full bg-green-500 ds-text py-2 px-4 ds-rounded-md"
                  disabled=move || verify_2fa_action.pending().get()
                >
                  {move || if verify_2fa_action.pending().get() {
                    "Verifying..."
                  } else {
                    "Enable 2FA"
                  }}
                </button>
              </form>
            </div>
          </div>
        }.into_any(),

        TwoFactorSetupState::Enabled(status) => view! {
          <div class="bg-green-50 border border-green-200 ds-rounded-lg p-ds-6 mb-6">
            <h2 class="ds-heading-4 mb-ds-4 text-green-800">
              "Two-Factor Authentication Enabled"
            </h2>
            <p class="text-green-700 mb-ds-4">
              "Your account is protected with two-factor authentication."
            </p>

            <div class="mb-ds-4">
              <p class="ds-caption ds-text-secondary">
                "Backup codes remaining: " {status.backup_codes_remaining.to_string()}
              </p>
            </div>

            <div>
              <p class="ds-caption ds-text-secondary">
                "Use the API endpoints to manage backup codes and disable 2FA."
              </p>
            </div>
          </div>
        }.into_any(),
      }}
    </div>
  }
}
