import React, { useState, useEffect } from "react";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";
import axios from "axios";

function setCookie(name: string, value: string, days = 7) {
  const expires = new Date(Date.now() + days * 864e5).toUTCString();
  document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/`;
}
function getCookie(name: string) {
  return document.cookie.split('; ').reduce((r, v) => {
    const parts = v.split('=');
    return parts[0] === name ? decodeURIComponent(parts[1]) : r;
  }, "");
}

const apiBase =
  typeof window !== "undefined" && window.location.hostname === "localhost"
    ? "http://localhost:8081/users"
    : "/users";

const API = axios.create({
  baseURL: apiBase,
});

interface HomepageAuthProps extends React.ComponentProps<"div"> {
  setLoggedIn: (loggedIn: boolean) => void;
  setIsAdmin: (isAdmin: boolean) => void;
  setUsername: (username: string | null) => void;
}

export function HomepageAuth({ className, setLoggedIn, setIsAdmin, setUsername, ...props }: HomepageAuthProps) {
  const [tab, setTab] = useState<"login" | "signup">("login");
  const [localUsername, setLocalUsername] = useState("");
  const [password, setPassword] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [internalLoggedIn, setInternalLoggedIn] = useState(false);
  const [firstUser, setFirstUser] = useState(false);
  const [dbError, setDbError] = useState<string | null>(null);
  const [registrationAllowed, setRegistrationAllowed] = useState(true);
  useEffect(() => {
    API.get("/registration-allowed").then(res => {
      setRegistrationAllowed(res.data.allowed);
    });
  }, []);

  useEffect(() => {
    API.get("/count").then(res => {
      if (res.data.count === 0) {
        setFirstUser(true);
        setTab("signup");
      } else {
        setFirstUser(false);
      }
      setDbError(null);
    }).catch(() => {
      setDbError("Could not connect to the database. Please try again later.");
    });
  }, []);

  useEffect(() => {
    const jwt = getCookie("jwt");
    if (jwt) {
      setLoading(true);
      Promise.all([
        API.get("/me", { headers: { Authorization: `Bearer ${jwt}` } }),
        API.get("/db-health")
      ])
        .then(([meRes]) => {
          setInternalLoggedIn(true);
          setLoggedIn(true);
          setIsAdmin(!!meRes.data.is_admin);
          setUsername(meRes.data.username || null);
          setDbError(null);
        })
        .catch((err) => {
          setInternalLoggedIn(false);
          setLoggedIn(false);
          setIsAdmin(false);
          setUsername(null);
          setCookie("jwt", "", -1);
          if (err?.response?.data?.error?.includes("Database")) {
            setDbError("Could not connect to the database. Please try again later.");
          } else {
            setDbError(null);
          }
        })
        .finally(() => setLoading(false));
    } else {
      setInternalLoggedIn(false);
      setLoggedIn(false);
      setIsAdmin(false);
      setUsername(null);
    }
  }, [setLoggedIn, setIsAdmin, setUsername]);

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    setLoading(true);
    try {
      let res, meRes;
      if (tab === "login") {
        res = await API.post("/get", { username: localUsername, password });
      } else {
        await API.post("/create", { username: localUsername, password });
        res = await API.post("/get", { username: localUsername, password });
      }
      setCookie("jwt", res.data.token);
      [meRes] = await Promise.all([
        API.get("/me", { headers: { Authorization: `Bearer ${res.data.token}` } }),
        API.get("/db-health")
      ]);
      setInternalLoggedIn(true);
      setLoggedIn(true);
      setIsAdmin(!!meRes.data.is_admin);
      setUsername(meRes.data.username || null);
      setDbError(null);
    } catch (err: any) {
      setError(err?.response?.data?.error || "Unknown error");
      setInternalLoggedIn(false);
      setLoggedIn(false);
      setIsAdmin(false);
      setUsername(null);
      setCookie("jwt", "", -1);
      if (err?.response?.data?.error?.includes("Database")) {
        setDbError("Could not connect to the database. Please try again later.");
      } else {
        setDbError(null);
      }
    } finally {
      setLoading(false);
    }
  }

  const Spinner = (
    <svg className="animate-spin mr-2 h-4 w-4 text-white inline-block" viewBox="0 0 24 24">
      <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
      <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" />
    </svg>
  );

  return (
    <div
      className={cn(
        "flex-1 flex justify-center items-center min-h-screen bg-background",
        className
      )}
      {...props}
    >
      <div className={`w-[420px] max-w-full bg-background rounded-xl shadow-lg p-6 flex flex-col ${internalLoggedIn ? '' : 'border border-border'}`}>
        {dbError && (
          <Alert variant="destructive" className="mb-4">
            <AlertTitle>Error</AlertTitle>
            <AlertDescription>{dbError}</AlertDescription>
          </Alert>
        )}
        {firstUser && !dbError && !internalLoggedIn && (
          <Alert variant="default" className="mb-4">
            <AlertTitle>First User</AlertTitle>
            <AlertDescription>
              You are the first user and will be made an admin. You can view admin settings in the sidebar user dropdown.
            </AlertDescription>
          </Alert>
        )}
        {!registrationAllowed && !internalLoggedIn && (
          <Alert variant="destructive" className="mb-4">
            <AlertTitle>Registration Disabled</AlertTitle>
            <AlertDescription>
              New account registration is currently disabled by an admin. Please log in or contact an administrator.
            </AlertDescription>
          </Alert>
        )}
        {(internalLoggedIn || (loading && getCookie("jwt"))) && (
          <div className="flex flex-1 justify-center items-center p-0 m-0">
            <div className="flex flex-col items-center gap-4">
              <Alert className="my-2">
                <AlertTitle>Logged in!</AlertTitle>
                <AlertDescription>
                  You are logged in!  Use the sidebar to access all available tools. To get started, create an SSH Host in the SSH Manager tab. Once created, you can connect to that host using the other apps in the sidebar.
                </AlertDescription>
              </Alert>
              
              <div className="flex flex-row items-center gap-2">
                <Button 
                  variant="link" 
                  className="text-sm"
                  onClick={() => window.open('https://github.com/LukeGus/Termix', '_blank')}
                >
                  GitHub
                </Button>
                <div className="w-px h-4 bg-border"></div>
                <Button 
                  variant="link" 
                  className="text-sm"
                  onClick={() => window.open('https://github.com/LukeGus/Termix/issues/new', '_blank')}
                >
                  Feedback
                </Button>
                <div className="w-px h-4 bg-border"></div>
                <Button 
                  variant="link" 
                  className="text-sm"
                  onClick={() => window.open('https://discord.com/invite/jVQGdvHDrf', '_blank')}
                >
                  Discord
                </Button>
                <div className="w-px h-4 bg-border"></div>
                <Button
                    variant="link"
                    className="text-sm"
                    onClick={() => window.open('https://github.com/sponsors/LukeGus', '_blank')}
                >
                  Fund
                </Button>
              </div>
            </div>
          </div>
        )}
        {(!internalLoggedIn && (!loading || !getCookie("jwt"))) && (
          <>
            <div className="flex gap-2 mb-6">
              <button
                type="button"
                className={cn(
                  "flex-1 py-2 text-base font-medium rounded-md transition-all",
                  tab === "login"
                    ? "bg-primary text-primary-foreground shadow"
                    : "bg-muted text-muted-foreground hover:bg-accent"
                )}
                onClick={() => setTab("login")}
                aria-selected={tab === "login"}
                disabled={loading || firstUser}
              >
                Login
              </button>
              <button
                type="button"
                className={cn(
                  "flex-1 py-2 text-base font-medium rounded-md transition-all",
                  tab === "signup"
                    ? "bg-primary text-primary-foreground shadow"
                    : "bg-muted text-muted-foreground hover:bg-accent"
                )}
                onClick={() => setTab("signup")}
                aria-selected={tab === "signup"}
                disabled={loading || !registrationAllowed}
              >
                Sign Up
              </button>
            </div>
            <div className="mb-6 text-center">
              <h2 className="text-xl font-bold mb-1">
                {tab === "login" ? "Login to your account" : "Create a new account"}
              </h2>
            </div>
            <form className="flex flex-col gap-5" onSubmit={handleSubmit}>
              <div className="flex flex-col gap-2">
                <Label htmlFor="username">Username</Label>
                <Input
                  id="username"
                  type="text"
                  required
                  className="h-11 text-base"
                  value={localUsername}
                  onChange={e => setLocalUsername(e.target.value)}
                  disabled={loading || internalLoggedIn}
                />
              </div>
              <div className="flex flex-col gap-2">
                <Label htmlFor="password">Password</Label>
                <Input id="password" type="password" required className="h-11 text-base" value={password} onChange={e => setPassword(e.target.value)} disabled={loading || internalLoggedIn} />
              </div>
              <Button type="submit" className="w-full h-11 mt-2 text-base font-semibold" disabled={loading || internalLoggedIn}>
                {loading ? Spinner : (tab === "login" ? "Login" : "Sign Up")}
              </Button>
            </form>
          </>
        )}
        {error && (
          <Alert variant="destructive" className="mt-4">
            <AlertTitle>Error</AlertTitle>
            <AlertDescription>{error}</AlertDescription>
          </Alert>
        )}
      </div>
    </div>
  );
}