import { Session, User as SupabaseUser } from "@supabase/supabase-js";
import { useMutation } from "@tanstack/react-query";
import { queryClient, toast, useSession } from "@xtablo/shared";
import { useSignUpToStream } from "@xtablo/shared/hooks/auth";
import { AxiosInstance } from "axios";
import { useState } from "react";
import { useNavigate } from "react-router-dom";
import { match } from "ts-pattern";
import { api } from "../lib/api";
import {
  DEFAULT_SIGNUP_BILLING_INTENT,
  PENDING_BILLING_CHECKOUT_PLAN_KEY,
  SIGNUP_BILLING_INTENT_KEY,
  SignupBillingIntent,
} from "../lib/billing";
import { supabase } from "../lib/supabase";

export type User = SupabaseUser & {
  user_metadata: {
    email: string;
    email_verified: boolean;
    first_name: string;
    last_name: string;
    business_name: string;
  };
};

interface SignUpData {
  email: string;
  password: string;
  confirm_password: string;
  first_name: string;
  last_name: string;
  business_name: string;
  billing_intent?: SignupBillingIntent;
}

interface LoginData {
  email: string;
  password: string;
}

interface AuthResponse {
  user: SupabaseUser | null;
  session: Session | null;
}

export const resolveSignupBillingIntent = (
  billingIntent?: SignupBillingIntent
): SignupBillingIntent => billingIntent ?? DEFAULT_SIGNUP_BILLING_INTENT;

export function useSignUp({ redirectUrl }: { redirectUrl: string | null }) {
  const navigate = useNavigate();
  const [errors, setErrors] = useState<Record<string, string>>({});
  const { signUpToStream } = useSignUpToStream(api);
  const { mutate, isPending } = useMutation<
    AuthResponse,
    { message: string; code: string },
    SignUpData
  >({
    mutationFn: async (data: SignUpData) => {
      const { data: response, error } = await supabase.auth.signUp({
        email: data.email,
        password: data.password,
        options: {
          emailRedirectTo: `${window.location.origin}/`,
          data: {
            first_name: data.first_name,
            last_name: data.last_name,
            business_name: data.business_name,
            billing_intent: resolveSignupBillingIntent(data.billing_intent),
          },
        },
      });
      if (error) throw error;

      // Only sign up to stream if user is immediately confirmed (auto-confirm enabled in Supabase)
      if (response.session?.access_token) {
        await signUpToStream(response.session.access_token);
      }
      return response;
    },
    onSuccess: async (data, variables) => {
      const selectedPlan = resolveSignupBillingIntent(variables.billing_intent);
      localStorage.setItem(SIGNUP_BILLING_INTENT_KEY, selectedPlan);
      localStorage.setItem(PENDING_BILLING_CHECKOUT_PLAN_KEY, selectedPlan);

      // If there's no session, it means email confirmation is required
      if (!data.user?.email_confirmed_at) {
        // Store the email for the confirmation page
        localStorage.setItem("pendingConfirmationEmail", data.user?.email || "");
        navigate("/confirm-email");
        return;
      }

      if (data.session?.access_token) {
        try {
          const checkoutResponse = await api.post(
            "/api/v1/stripe/create-checkout-session",
            {
              plan: selectedPlan,
              successUrl: `${window.location.origin}/settings?success=true`,
              cancelUrl: `${window.location.origin}/settings?canceled=true`,
            },
            {
              headers: {
                Authorization: `Bearer ${data.session.access_token}`,
              },
            }
          );

          if (checkoutResponse.data?.url) {
            localStorage.removeItem(SIGNUP_BILLING_INTENT_KEY);
            localStorage.removeItem(PENDING_BILLING_CHECKOUT_PLAN_KEY);
            window.location.href = checkoutResponse.data.url;
            return;
          }
        } catch (error) {
          console.error("Signup checkout bootstrap failed after signup:", error);
          toast.add({
            title: "Paiement",
            description:
              "Votre compte est créé, mais la redirection vers le paiement a échoué. Vous pourrez finaliser le paiement dans l'application.",
            type: "warning",
            position: "top-center",
          });
        }
      }

      localStorage.removeItem(SIGNUP_BILLING_INTENT_KEY);

      if (redirectUrl) {
        localStorage.removeItem("redirectUrl");
        navigate(decodeURIComponent(redirectUrl));
        return;
      }

      navigate("/");
    },
    onError: (error) => {
      const errMap: Record<string, string> = {};

      match(error.code)
        .with("user_already_exists", () => {
          errMap["email"] = "Cette adresse email est déjà utilisée";
        })
        .otherwise(() => {
          toast.add(
            {
              title: "Erreur",
              description: error.message,
              type: "error",
              position: "top-left",
            },
            {
              timeout: 5000,
            }
          );
        });

      setErrors(errMap);
    },
  });
  return { mutate, isPending, errors };
}

export function useLoginEmail({ redirectUrl }: { redirectUrl: string | null }) {
  const navigate = useNavigate();
  const [errors, setErrors] = useState<Record<string, string>>({});
  const { signUpToStream } = useSignUpToStream(api);
  const { mutate, isPending } = useMutation<
    AuthResponse,
    { message: string; code: string },
    LoginData
  >({
    mutationFn: async (data: LoginData) => {
      const { data: response, error } = await supabase.auth.signInWithPassword({
        email: data.email.trim(),
        password: data.password.trim(),
      });
      if (error) throw error;
      if (response.session?.access_token) {
        await signUpToStream(response.session.access_token);
      }
      return response;
    },
    onSuccess: (data) => {
      // Check if email is verified
      if (data.user && !data.user.email_confirmed_at) {
        // Email not verified, redirect to confirmation page
        localStorage.setItem("pendingConfirmationEmail", data.user.email || "");
        toast.add({
          title: "Email non vérifié",
          description: "Veuillez vérifier votre email avant de vous connecter",
          type: "warning",
          position: "top-center",
        });
        navigate("/confirm-email");
        return;
      }

      // Email verified, proceed with login
      if (redirectUrl) {
        localStorage.removeItem("redirectUrl");
        navigate(decodeURIComponent(redirectUrl));
      } else {
        navigate("/");
      }
    },
    onError: (error) => {
      match(error.code)
        .with("invalid_credentials", () => {
          setErrors({ email: "Email ou mot de passe incorrect" });
        })
        .with("email_not_confirmed", () => {
          toast.add(
            {
              title: "Email non vérifié",
              description: "Veuillez vérifier votre email avant de vous connecter",
              type: "warning",
              position: "top-center",
            },
            {
              timeout: 7000,
            }
          );
          navigate("/confirm-email");
        })
        .otherwise(() => {
          toast.add(
            {
              title: "Erreur",
              description: error.message,
              type: "error",
              position: "top-left",
            },
            {
              timeout: 5000,
            }
          );
        });
    },
  });
  return { mutate, isPending, errors };
}

export function useLoginGoogle() {
  const { mutate } = useMutation({
    mutationFn: async () => {
      const { data, error } = await supabase.auth.signInWithOAuth({
        provider: "google",
        options: {
          redirectTo: `${window.location.origin}/login-with-oauth`,
        },
      });
      if (error) throw error;
      return data;
    },
  });
  return { loginWithGoogle: mutate };
}

export function useLogout() {
  return useMutation({
    mutationFn: async () => {
      const { error } = await supabase.auth.signOut();
      if (error) throw error;
      queryClient.removeQueries();
    },
    onSuccess: () => {
      toast.add({
        title: "Déconnexion réussie",
        description: "Vous avez été déconnecté avec succès",
        type: "success",
      });
    },
    onError: (error) => {
      toast.add({
        title: "Erreur",
        description: error.message,
        type: "error",
      });
    },
  });
}

export const useAuthedApi = (): AxiosInstance => {
  const { session } = useSession();
  return api.create({
    headers: {
      Authorization: `Bearer ${session?.access_token}`,
    },
  });
};

export function useResendConfirmationEmail() {
  const { mutate, isPending } = useMutation({
    mutationFn: async (email: string) => {
      const { error } = await supabase.auth.resend({
        type: "signup",
        email: email,
        options: {
          emailRedirectTo: `${window.location.origin}/`,
        },
      });
      if (error) throw error;
    },
    onSuccess: () => {
      toast.add({
        title: "Email envoyé",
        description: "Un nouvel email de confirmation vous a été envoyé",
        type: "success",
        position: "top-center",
      });
    },
    onError: (error: Error) => {
      toast.add({
        title: "Erreur",
        description: error.message || "Impossible d'envoyer l'email de confirmation",
        type: "error",
        position: "top-center",
      });
    },
  });
  return { mutate, isPending };
}
