import { Button } from "@/shared/ui/button";
import { Dialog, DialogContent, DialogTrigger } from "@/shared/ui/dialog";

import {
  fetchSiwePayload,
  fetchSiweStatus,
  fetchSiweVerify,
} from "@/shared/lib/siwe/api";
import { DialogTitle } from "@radix-ui/react-dialog";
import { useQuery } from "@tanstack/react-query";
import { type IDetectedBarcode, Scanner } from "@yudiel/react-qr-scanner";
import { useEffect, useState } from "react";
import { useActiveAccount } from "thirdweb/react";
import { redeem, useEventStatus } from "../api/redeem";

export type RedeemProps = {
  eventId: number;
};

// TODO: Add error handling
export const Redeem: React.FC<RedeemProps> = ({ eventId }) => {
  const account = useActiveAccount();
  const { data } = useQuery(useEventStatus(eventId));
  const [proofToken, setProofToken] = useState<string | null>(null);
  const [isSigning, setIsSigning] = useState(false);
  const [isTrusted, setIsTrusted] = useState(false);

  useEffect(() => {
    const addr = account?.address;
    if (!addr) {
      setProofToken(null);
      setIsTrusted(false);
      return;
    }

    fetchSiweStatus({ address: addr, scope: "ticket:verify" })
      .then((s) => {
        setIsTrusted(s.trusted);
        setProofToken(s.trusted ? "cookie" : null);
      })
      .catch(() => {
        setIsTrusted(false);
        setProofToken(null);
      });
  }, [account?.address]);

  const signToVerify = async () => {
    if (!account) {
      alert("No active wallet");
      return;
    }
    setIsSigning(true);
    try {
      const addr = account.address;
      const { payload, message } = await fetchSiwePayload({
        address: addr,
        purpose: "staff_verify",
      });
      const signature = await account.signMessage({ message });
      await fetchSiweVerify({ payload, signature });
      setIsTrusted(true);
      setProofToken("cookie");
    } catch (e) {
      console.error(e);
      alert("Failed to sign");
    } finally {
      setIsSigning(false);
    }
  };

  async function handleDetect(detected: IDetectedBarcode[]) {
    const value = detected.at(0);
    if (!value) return;
    try {
      await redeem(account, value.rawValue, proofToken);
    } catch (e) {
      alert("Failed to redeem ticket");
    }
  }

  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button className="w-full">Redeem ticket</Button>
      </DialogTrigger>
      <DialogContent aria-describedby={undefined} className="p-16">
        <DialogTitle className="text-center text-3xl">Scan ticket</DialogTitle>
        {!isTrusted ? (
          <div className="flex flex-col items-center gap-4">
            <p className="text-muted-foreground text-center">
              Staff verification requires a signed message.
            </p>
            <Button
              onClick={signToVerify}
              disabled={isSigning}
              className="w-full"
            >
              {isSigning ? "Signing..." : "Sign to start scanning"}
            </Button>
          </div>
        ) : (
          <Scanner onScan={handleDetect} />
        )}
        {/* NOTE: IDK why openapi-typescript marks it as possible undefined */}
        {data?.tickets && (
          <div className="text-center">
            <p>
              <span>Total tickets:</span>
              {data.tickets.total}
            </p>
            <p>
              <span>Redeemed:</span>
              {data.tickets.redeemed}
            </p>
          </div>
        )}
      </DialogContent>
    </Dialog>
  );
};

Graph