"use client";

import * as React from "react";

import Link from "next/link";
import Image from "next/image";

import { useRouter } from "next/navigation";

import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod"
import { Controller, useForm } from "react-hook-form"

import { toast } from "sonner";

import { Card, CardHeader, CardTitle, CardContent, CardDescription } from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";

import UseAnimations from "react-useanimations";
import checkAnimation from "react-useanimations/lib/checkmark";

import {
  Field,
  FieldError,
  FieldGroup,
  FieldLabel,
} from "@/components/ui/field";

import { SocialLoginButton } from "@/components/core/social-login-button";

import { login } from "@/components/server/login";

import { IconBrandGithub, IconBrandGoogle, IconHomeFilled, IconUserCircle, IconLogout, IconChevronRight } from "@tabler/icons-react";
import { Spinner } from "@/components/ui/spinner";

const loginSchema = z.object({
  username: z.string().min(3, "Username must be at least 3 characters long"),
  password: z.string().min(8, "Password must be at least 8 characters long"),
});

export interface LoginFormProps {
  applicationName: string;
  applicationLogo?: string;
}

export const LoginForm = () => {
  const form = useForm<z.infer<typeof loginSchema>>({
    resolver: zodResolver(loginSchema),
    defaultValues: {
      username: "",
      password: "",
    },
  });

  const onSubmit = async (data: z.infer<typeof loginSchema>) => {
    const response = await login(data.username, data.password);
    if (response.success) {
      toast.success(response.message);
    } else {
      toast.error(response.message);
    }
  };

  return (
    <form id="form-login" onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-6 px-6">
      <div className="flex flex-col">
        <FieldGroup>
          <Controller 
            name="username" 
            control={form.control} 
            render={({ field }) => (
              <Field className="flex flex-col gap-2">
                <FieldLabel>Username</FieldLabel>
                <Input 
                  {...field} 
                  type="text"
                  placeholder="Enter your username" 
                  className="text-sm" 
                  id="form-login-username" 
                  autoComplete="username" 
                />
                <FieldError className="text-violet-900 text-xs" errors={form.formState.errors.username ? [form.formState.errors.username] : undefined} />
              </Field>
            )} 
          />
          <Controller 
            name="password" 
            control={form.control} 
            render={({ field }) => (
              <Field className="flex flex-col gap-2">
                <FieldLabel>Password</FieldLabel>
                <Input 
                  {...field} 
                  type="password" 
                  placeholder="Enter your password" 
                  className="text-sm" 
                  id="form-login-password" 
                  autoComplete="current-password" 
                />
                <FieldError className="text-violet-900 text-xs" errors={form.formState.errors.password ? [form.formState.errors.password] : undefined} />
              </Field>
            )} 
          />
        </FieldGroup>
      </div>
      <Field>
        <Button type="submit" className="w-full bg-violet-900 text-primary-foreground hover:bg-violet-800">Login</Button>
      </Field>
    </form>
  );
};

export const LoginContainer = (props: LoginFormProps) => {
  const { applicationName, applicationLogo } = props;  

  return (
    <div className="flex flex-col gap-6 w-full max-w-sm">
      <Card className="flex flex-col p-0">
        <CardHeader className="flex flex-col gap-4 justify-center items-center pt-6">
          <CardTitle className="flex flex-row items-center justify-center gap-1 text-2xl font-bold text-center">
            {applicationLogo && <Image src={applicationLogo} alt={applicationName} width={100} height={100} />}
            {!applicationLogo && (
              <IconHomeFilled className="w-6 h-6" />
            )}
            <Label className="text-2xl font-bold text-center">{applicationName}</Label>
          </CardTitle>
          <CardDescription className="text-center">
            <div className="flex flex-col gap-2">
              <p className="text-zinc-700 dark:text-zinc-300 font-bold text-md">Login to your account</p>
              <p className="text-zinc-500 text-sm">Welcome back! Please sign in to continue.</p>
            </div>
          </CardDescription>
        </CardHeader>
        <CardContent className="flex flex-col gap-6 px-0">
          <div className="flex flex-col gap-6 pb-4">
            <div className="flex flex-row gap-2 px-6 justify-between items-center w-full">
              <SocialLoginButton icon={<IconBrandGithub className="w-4 h-4" />} label="GitHub" onClick={() => {}} />
              <SocialLoginButton icon={<IconBrandGoogle className="w-4 h-4" />} label="Google" onClick={() => {}} />
            </div>
            <Separator className="w-full" />
            <div className="flex flex-col gap-6">
              <LoginForm />
              <div className="flex flex-col gap-4">
                <Separator className="w-full" />
                <div className="flex flex-col gap-4">
                  <div className="flex flex-col gap-4 items-center justify-center">
                    <p className="text-zinc-500 text-sm">Don&apos;t have an account? <Link href="/register" className="text-violet-800 dark:text-violet-300 font-bold">Sign up</Link></p>
                  </div>
                </div>
                <Separator className="w-full" />
                <div className="flex flex-col gap-4 items-center justify-center">
                  <Label className="text-zinc-700 dark:text-zinc-300 font-medium text-xs">Secured by SecNex</Label>
                </div>
              </div>
            </div>
          </div>
        </CardContent>
      </Card>
    </div>
  );
};

export const LoginLoading = (props: LoginFormProps) => {
  const { applicationName, applicationLogo } = props;
  
  return (
    <div className="flex flex-col gap-6 w-full max-w-md">
      <Card className="flex flex-col p-0">
        <CardHeader className="flex flex-col gap-4 justify-center items-center pt-6">
          <CardTitle className="flex flex-row items-center justify-center gap-1 text-2xl font-bold text-center">
            {applicationLogo && <Image src={applicationLogo} alt={applicationName} width={100} height={100} />}
            {!applicationLogo && (
              <IconHomeFilled className="w-6 h-6" />
            )}
            <Label className="text-2xl font-bold text-center">{applicationName}</Label>
          </CardTitle>
        </CardHeader>
        <CardContent className="flex flex-col gap-6 px-0 pt-6">
          <div className="flex flex-col gap-6 px-6">
            <div className="flex justify-center items-center gap-6 pb-4">
              <div className="flex flex-col gap-2 bg-violet-200 rounded-full p-4">
                <div className="flex justify-center items-center gap-6 border-2 border-violet-900 rounded-full">
                  <Spinner className="size-8 animate-spin text-violet-900" />
                </div>
              </div>
            </div>
          </div>
          <Separator className="w-full" />
          <div className="flex flex-col gap-4 items-center justify-center w-full px-6 pb-6">
            <Label className="text-zinc-700 dark:text-zinc-300 font-medium text-xs text-center">Secured by SecNex</Label>
          </div>
        </CardContent>
      </Card>
    </div>
  );
};

export const LoginSuccessContainer = (props: LoginFormProps) => {
  const [isLoading, setIsLoading] = React.useState(true);
  const [sessionInfo, setSessionInfo] = React.useState<{ username: string, email: string, role: string } | null>(null);

  const router = useRouter();
  
  const { applicationName, applicationLogo } = props;

  const handleLogout = async () => {
    const response = await fetch("/api/logout");
    const data = await response.json();
    if (data.success) {
      toast.success(data.message);
      router.refresh();
    } else {
      toast.error(data.message);
    }
    setIsLoading(false);
  };

  React.useEffect(() => {
    const checkSession = async () => {
      const response = await fetch("/api/session");
      const data = await response.json();
      if (data.success) {
        setSessionInfo(data.sessionInfo);
        setIsLoading(false);
      } else {
        router.refresh();
      }
    };
    checkSession();
  }, [router]);

  if (isLoading) {
    return <LoginLoading applicationName={applicationName} applicationLogo={applicationLogo} />;
  }
  
  return (
    <div className="flex flex-col gap-6 w-full max-w-md">
      <Card className="flex flex-col p-0">
        <CardHeader className="flex flex-col gap-4 justify-center items-center pt-6">
          <CardTitle className="flex flex-row items-center justify-center gap-1 text-2xl font-bold text-center">
            {applicationLogo && <Image src={applicationLogo} alt={applicationName} width={100} height={100} />}
            {!applicationLogo && (
              <IconHomeFilled className="w-6 h-6" />
            )}
            <Label className="text-2xl font-bold text-center">{applicationName}</Label>
          </CardTitle>
        </CardHeader>
        <CardContent className="flex flex-col gap-6 px-0 pt-6">
          <div className="flex flex-col gap-6 px-6">
            <div className="flex justify-center items-center gap-6 pb-4">
              <div className="flex flex-col gap-2 bg-violet-200 rounded-full p-4">
                <div className="flex justify-center items-center gap-6 border-2 border-violet-900 rounded-full">
                  <UseAnimations animation={checkAnimation} size={32} strokeColor="#44168f" fillColor="#44168f" loop={false} />
                </div>
              </div>
            </div>
            <div className="flex flex-col gap-2 items-center justify-center">
              <Label className="text-zinc-700 dark:text-zinc-300 font-bold text-lg">Successfully signed in</Label>
              <p className="text-zinc-700 dark:text-zinc-300 font-medium text-xs text-wrap break-all">Welcome back, <span className="font-bold">{sessionInfo?.username}</span>!</p>
            </div>
            <div className="flex flex-row gap-4 items-center bg-violet-50 border border-violet-200 rounded-lg p-4">
              <div className="flex flex-row gap-2 items-center justify-center">
                <div className="flex justify-center items-center gap-4 bg-violet-200 rounded-full p-3">
                  <IconUserCircle className="w-6 h-6 text-violet-900" />
                </div>
              </div>
              <div className="flex flex-col gap-1">
                <Label className="text-zinc-900 dark:text-zinc-300 text-md">{sessionInfo?.username}</Label>
                <p className="text-zinc-700 dark:text-zinc-300 text-xs text-wrap break-all">{sessionInfo?.email}</p>
              </div>
            </div>
          </div>
          <div className="flex flex-col gap-4 items-center justify-center w-full px-6">
            <Button variant="outline" className="border-violet-900 text-violet-900 hover:text-violet-800 hover:bg-violet-50 w-full">Go to dashboard <IconChevronRight className="w-4 h-4" /></Button>
            <Button variant="outline" className="border-violet-900 bg-violet-900 text-violet-50 hover:bg-violet-800 hover:text-violet-100 w-full" onClick={handleLogout}><IconLogout className="w-4 h-4" /> Logout</Button>
          </div>
          <Separator className="w-full" />
          <div className="flex flex-col gap-4 items-center justify-center w-full px-6 pb-6">
            <Label className="text-zinc-700 dark:text-zinc-300 font-medium text-xs text-center">Secured by SecNex</Label>
          </div>
        </CardContent>
      </Card>
    </div>
  );
};