import React from "react";
import { useLocation, useNavigate } from "react-router";
import PasswordInput from "src/components/password/PasswordInput";
import TwoColumnLayoutHeader from "src/components/TwoColumnLayoutHeader";
import { LoadingButton } from "src/components/ui/custom/loading-button";
import { Label } from "src/components/ui/label";

import { useInfo } from "src/hooks/useInfo";
import { saveAuthToken } from "src/lib/auth";
import { hasNip07Signer } from "src/lib/nip07";
import { AuthTokenResponse } from "src/types";
import { handleRequestError } from "src/utils/handleRequestError";
import { request } from "src/utils/request";

export default function Unlock() {
  const [unlockPassword, setUnlockPassword] = React.useState("");
  const [loading, setLoading] = React.useState(false);
  const navigate = useNavigate();
  const location = useLocation();

  const { data: info } = useInfo();
  const { mutate: refetchInfo } = useInfo();

  React.useEffect(() => {
    if (!info || info.running) {
      return;
    }
    navigate("/");
  }, [info, location, navigate]);

  async function onSubmit(e: React.FormEvent) {
    e.preventDefault();
    try {
      setLoading(true);

      const authTokenResponse = await request<AuthTokenResponse>(
        "/api/unlock",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({
            unlockPassword,
            permission: "full",
          }),
        }
      );
      if (authTokenResponse) {
        saveAuthToken(authTokenResponse.token);
      }
      await refetchInfo();
      navigate("/");
    } catch (error) {
      handleRequestError("Failed to connect", error);
    } finally {
      setLoading(false);
    }
  }

  async function onNip07SignIn() {
    try {
      setLoading(true);

      const challengeResponse = await request<{
        challenge: string;
        pubkey: string;
      }>("/api/nip07/challenge");
      if (!challengeResponse) {
        throw new Error("Failed to get challenge");
      }

      const signedEvent = await window.nostr!.signEvent({
        kind: 27235,
        created_at: Math.floor(Date.now() / 1000),
        tags: [["challenge", challengeResponse.challenge]],
        content: "",
      });

      await request("/api/nip07/auth", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          challenge: challengeResponse.challenge,
          event: signedEvent,
        }),
      });

      await refetchInfo();
      navigate("/");
    } catch (error) {
      handleRequestError("Failed to sign in", error);
    } finally {
      setLoading(false);
    }
  }

  if (info?.nip07AuthEnabled) {
    return (
      <div className="w-full p-5">
        <div className="mx-auto grid w-80 max-w-full gap-6">
          <TwoColumnLayoutHeader
            title="Login"
            pageTitle="Login"
            description="Sign in with your Nostr extension to continue"
          />
          {hasNip07Signer() ? (
            <LoadingButton loading={loading} onClick={onNip07SignIn}>
              Sign in with Nostr
            </LoadingButton>
          ) : (
            <p className="text-sm text-muted-foreground">
              No NIP-07 signer detected. Install a Nostr browser extension (e.g.
              Alby) and refresh to sign in.
            </p>
          )}
        </div>
      </div>
    );
  }

  return (
    <form onSubmit={onSubmit} className="w-full p-5">
      <div className="mx-auto grid w-80 max-w-full gap-6">
        <TwoColumnLayoutHeader
          title="Login"
          pageTitle="Login"
          description="Enter your unlock password to continue"
        />
        <div className="grid gap-4">
          <div className="grid gap-1.5">
            <Label htmlFor="password">Password</Label>
            <PasswordInput
              id="password"
              onChange={setUnlockPassword}
              autoFocus
              value={unlockPassword}
            />
          </div>
          <LoadingButton type="submit" loading={loading}>
            Login
          </LoadingButton>
        </div>
      </div>
    </form>
  );
}
