"use client";

import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import Link from "next/link";
import {
  ScanLine,
  Loader2,
  CheckCircle2,
  XCircle,
  LogIn,
  LogOut,
  Mail,
  User as UserIcon,
  Clock,
  AlertCircle,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useSession, signIn, signOut } from "next-auth/react";
import { toast } from "sonner";
import { PasswordFields } from "@/components/auth/password-fields";

type VerifyResponse =
  | {
      valid: true;
      email: string;
      role: string;
      orgName: string;
      inviterName: string | null;
      hasExistingAccount: boolean;
    }
  | {
      valid: false;
      reason: "not_found" | "expired" | "accepted";
      orgName?: string;
      inviterName?: string;
    };

type Stage =
  | { kind: "loading" }
  | { kind: "invalid"; reason: "not_found" | "expired" | "accepted"; orgName?: string; inviterName?: string }
  | { kind: "accepted"; orgName: string }
  | {
      kind: "valid";
      email: string;
      role: string;
      orgName: string;
      inviterName: string | null;
      hasExistingAccount: boolean;
    };

export default function InvitePage() {
  const params = useParams();
  const { data: session, status: sessionStatus } = useSession();
  const token = params.token as string;
  const [stage, setStage] = useState<Stage>({ kind: "loading" });

  useEffect(() => {
    fetch(`/api/invitations/verify?token=${token}`)
      .then((r) => r.json() as Promise<VerifyResponse>)
      .then((data) => {
        if (data.valid) {
          setStage({
            kind: "valid",
            email: data.email,
            role: data.role,
            orgName: data.orgName,
            inviterName: data.inviterName,
            hasExistingAccount: data.hasExistingAccount,
          });
        } else {
          setStage({
            kind: "invalid",
            reason: data.reason,
            orgName: data.orgName,
            inviterName: data.inviterName,
          });
        }
      })
      .catch(() => setStage({ kind: "invalid", reason: "not_found" }));
  }, [token]);

  if (stage.kind === "loading" || sessionStatus === "loading") {
    return (
      <div className="glass-card mx-auto flex w-full max-w-md flex-col items-center rounded-2xl p-8">
        <Loader2 className="size-8 animate-spin text-muted-foreground" />
        <p className="mt-4 text-sm text-muted-foreground">Verifying invitation...</p>
      </div>
    );
  }

  if (stage.kind === "accepted") {
    return (
      <div className="glass-card mx-auto flex w-full max-w-md flex-col items-center rounded-2xl p-8 text-center">
        <CheckCircle2 className="mb-4 size-12 text-emerald-500" />
        <h1 className="text-xl font-bold">Welcome!</h1>
        <p className="mt-2 text-sm text-muted-foreground">
          You&apos;ve joined <strong>{stage.orgName}</strong>. Redirecting...
        </p>
        <Loader2 className="mt-4 size-5 animate-spin text-muted-foreground" />
      </div>
    );
  }

  if (stage.kind === "invalid") {
    return <InvalidInvite reason={stage.reason} orgName={stage.orgName} inviterName={stage.inviterName} />;
  }

  const isLoggedIn = sessionStatus === "authenticated" && session?.user;
  const emailMatch =
    !!isLoggedIn && session.user.email?.toLowerCase() === stage.email.toLowerCase();

  const onAccepted = (orgName: string) => {
    setStage({ kind: "accepted", orgName });
    setTimeout(() => {
      window.location.href = "/";
    }, 1200);
  };

  return (
    <div className="glass-card mx-auto flex w-full max-w-md flex-col rounded-2xl p-8">
      <InviteHeader
        orgName={stage.orgName}
        role={stage.role}
        inviterName={stage.inviterName}
        email={stage.email}
      />

      <div className="mt-6 flex w-full flex-col gap-3">
        {isLoggedIn && emailMatch ? (
          <AcceptBlock token={token} onAccepted={onAccepted} />
        ) : isLoggedIn && !emailMatch ? (
          <MismatchBlock
            token={token}
            currentEmail={session?.user?.email || ""}
            inviteEmail={stage.email}
          />
        ) : stage.hasExistingAccount ? (
          <LoginBlock
            token={token}
            email={stage.email}
            orgName={stage.orgName}
            onAccepted={onAccepted}
          />
        ) : (
          <SignupBlock
            token={token}
            email={stage.email}
            orgName={stage.orgName}
            onAccepted={onAccepted}
          />
        )}
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  Header                                                             */
/* ------------------------------------------------------------------ */

function InviteHeader({
  orgName,
  role,
  inviterName,
  email,
}: {
  orgName: string;
  role: string;
  inviterName: string | null;
  email: string;
}) {
  return (
    <div className="flex flex-col items-center text-center">
      <div className="mb-4 flex size-14 items-center justify-center rounded-2xl gradient-banner shadow-lg">
        <ScanLine className="size-7 text-white" />
      </div>
      <h1 className="text-xl font-bold">You&apos;re invited to {orgName}</h1>
      <p className="mt-2 text-sm text-muted-foreground">
        {inviterName ? (
          <>
            <strong>{inviterName}</strong> invited you to join{" "}
            <strong>{orgName}</strong> as a <strong>{role}</strong>.
          </>
        ) : (
          <>
            You&apos;ve been invited to join <strong>{orgName}</strong> as a{" "}
            <strong>{role}</strong>.
          </>
        )}
      </p>
      <p className="mt-2 inline-flex items-center gap-1.5 rounded-full bg-muted/60 px-3 py-1 text-xs text-muted-foreground">
        <Mail className="size-3" />
        {email}
      </p>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/*  Branches                                                           */
/* ------------------------------------------------------------------ */

function AcceptBlock({
  token,
  onAccepted,
}: {
  token: string;
  onAccepted: (orgName: string) => void;
}) {
  const [accepting, setAccepting] = useState(false);

  async function handleAccept() {
    setAccepting(true);
    try {
      const res = await fetch("/api/invitations/accept", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ token }),
      });
      const data = await res.json();
      if (!res.ok) {
        toast.error(data.error || "Failed to accept invitation");
        setAccepting(false);
        return;
      }
      await fetch("/api/auth/session");
      onAccepted(data.orgName);
    } catch {
      toast.error("Failed to accept invitation");
      setAccepting(false);
    }
  }

  return (
    <Button
      className="w-full rounded-xl"
      onClick={handleAccept}
      disabled={accepting}
    >
      {accepting ? (
        <>
          <Loader2 className="mr-2 size-4 animate-spin" /> Joining...
        </>
      ) : (
        "Accept Invitation"
      )}
    </Button>
  );
}

function MismatchBlock({
  token,
  currentEmail,
  inviteEmail,
}: {
  token: string;
  currentEmail: string;
  inviteEmail: string;
}) {
  const [signingOut, setSigningOut] = useState(false);
  return (
    <>
      <div className="rounded-lg border border-amber-200 bg-amber-50 p-3 text-left text-xs text-amber-800 dark:border-amber-900/40 dark:bg-amber-950/30 dark:text-amber-200">
        <p className="flex items-start gap-2">
          <AlertCircle className="mt-0.5 size-3.5 shrink-0" />
          <span>
            You&apos;re signed in as <strong>{currentEmail}</strong>, but this invitation
            was sent to <strong>{inviteEmail}</strong>. Sign out to continue as the
            invited user.
          </span>
        </p>
      </div>
      <Button
        variant="outline"
        className="w-full rounded-xl"
        disabled={signingOut}
        onClick={() => {
          setSigningOut(true);
          signOut({ callbackUrl: `/invite/${token}` });
        }}
      >
        {signingOut ? (
          <Loader2 className="mr-2 size-4 animate-spin" />
        ) : (
          <LogOut className="mr-2 size-4" />
        )}
        Sign out and continue
      </Button>
    </>
  );
}

function LoginBlock({
  token,
  email,
  orgName,
  onAccepted,
}: {
  token: string;
  email: string;
  orgName: string;
  onAccepted: (orgName: string) => void;
}) {
  const [password, setPassword] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError("");
    setLoading(true);

    const result = await signIn("credentials", {
      email,
      password,
      redirect: false,
    });

    if (result?.error) {
      setError("Invalid password. Please try again.");
      setLoading(false);
      return;
    }

    try {
      const res = await fetch("/api/invitations/accept", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ token }),
      });
      const data = await res.json();
      if (!res.ok) {
        setError(data.error || "Failed to accept invitation");
        setLoading(false);
        return;
      }
      onAccepted(data.orgName || orgName);
    } catch {
      setError("Something went wrong. Please try again.");
      setLoading(false);
    }
  }

  return (
    <>
      <p className="text-center text-xs text-muted-foreground">
        An account already exists for this email. Enter your password to sign in and
        join <strong>{orgName}</strong>.
      </p>
      {error && (
        <div className="rounded-lg bg-destructive/10 p-3 text-center text-sm text-destructive">
          {error}
        </div>
      )}
      <form onSubmit={handleSubmit} className="space-y-3">
        <PasswordFields
          password={password}
          onPasswordChange={setPassword}
          passwordLabel="Password"
          passwordPlaceholder="Enter your password"
          passwordId="invite-login-password"
          showStrengthMeter={false}
          showConfirmField={false}
          autoComplete="current-password"
          required
        />
        <Button type="submit" className="w-full rounded-xl" disabled={loading || !password}>
          {loading ? (
            <Loader2 className="mr-2 size-4 animate-spin" />
          ) : (
            <LogIn className="mr-2 size-4" />
          )}
          Sign in & Join
        </Button>
      </form>
      <p className="text-center text-xs text-muted-foreground">
        <Link
          href={`/forgot-password?email=${encodeURIComponent(email)}`}
          className="hover:underline"
        >
          Forgot your password?
        </Link>
      </p>
    </>
  );
}

function SignupBlock({
  token,
  email,
  orgName,
  onAccepted,
}: {
  token: string;
  email: string;
  orgName: string;
  onAccepted: (orgName: string) => void;
}) {
  const [displayName, setDisplayName] = useState("");
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError("");

    if (password !== confirmPassword) {
      setError("Passwords do not match");
      return;
    }
    if (password.length < 8) {
      setError("Password must be at least 8 characters");
      return;
    }

    setLoading(true);

    try {
      const res = await fetch("/api/auth/register", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          displayName,
          email,
          password,
          inviteToken: token,
        }),
      });

      if (!res.ok) {
        const data = await res.json();
        setError(data.error || "Registration failed");
        setLoading(false);
        return;
      }

      const signInResult = await signIn("credentials", {
        email,
        password,
        redirect: false,
      });

      if (signInResult?.error) {
        setError("Account created, but sign-in failed. Please try signing in.");
        setLoading(false);
        return;
      }

      onAccepted(orgName);
    } catch {
      setError("Something went wrong. Please try again.");
      setLoading(false);
    }
  }

  return (
    <>
      {error && (
        <div className="rounded-lg bg-destructive/10 p-3 text-center text-sm text-destructive">
          {error}
        </div>
      )}
      <form onSubmit={handleSubmit} className="space-y-4">
        <div className="space-y-2">
          <Label htmlFor="invite-signup-name">Full name</Label>
          <div className="relative">
            <UserIcon className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
            <Input
              id="invite-signup-name"
              type="text"
              placeholder="John Smith"
              value={displayName}
              onChange={(e) => setDisplayName(e.target.value)}
              required
              className="pl-10"
            />
          </div>
        </div>

        <PasswordFields
          password={password}
          confirmPassword={confirmPassword}
          onPasswordChange={setPassword}
          onConfirmChange={setConfirmPassword}
          passwordId="invite-signup-password"
          confirmId="invite-signup-confirm"
        />

        <Button type="submit" className="w-full rounded-xl" disabled={loading}>
          {loading ? <Loader2 className="mr-2 size-4 animate-spin" /> : null}
          Create account & Join {orgName}
        </Button>
      </form>
      <p className="mt-3 text-center text-[10px] text-muted-foreground/60">
        By creating an account, you agree to our{" "}
        <Link href="/terms" className="underline hover:text-muted-foreground">
          Terms
        </Link>{" "}
        and{" "}
        <Link href="/privacy" className="underline hover:text-muted-foreground">
          Privacy Policy
        </Link>
        .
      </p>
    </>
  );
}

/* ------------------------------------------------------------------ */
/*  Invalid states (expired / accepted / not found)                    */
/* ------------------------------------------------------------------ */

function InvalidInvite({
  reason,
  orgName,
  inviterName,
}: {
  reason: "not_found" | "expired" | "accepted";
  orgName?: string;
  inviterName?: string;
}) {
  if (reason === "expired") {
    return (
      <div className="glass-card mx-auto flex w-full max-w-md flex-col items-center rounded-2xl p-8 text-center">
        <Clock className="mb-4 size-12 text-amber-500" />
        <h1 className="text-xl font-bold">Invitation expired</h1>
        <p className="mt-2 text-sm text-muted-foreground">
          {orgName ? (
            <>
              Your invitation to <strong>{orgName}</strong> has expired.
            </>
          ) : (
            <>This invitation has expired.</>
          )}{" "}
          {inviterName ? (
            <>
              Ask <strong>{inviterName}</strong> to send you a new one.
            </>
          ) : (
            <>Ask the person who invited you to send a new one.</>
          )}
        </p>
        <Link href="/login">
          <Button variant="outline" className="mt-6 rounded-xl">
            Go to Login
          </Button>
        </Link>
      </div>
    );
  }

  if (reason === "accepted") {
    return (
      <div className="glass-card mx-auto flex w-full max-w-md flex-col items-center rounded-2xl p-8 text-center">
        <CheckCircle2 className="mb-4 size-12 text-emerald-500" />
        <h1 className="text-xl font-bold">Invitation already used</h1>
        <p className="mt-2 text-sm text-muted-foreground">
          {orgName ? (
            <>
              This invitation to <strong>{orgName}</strong> has already been accepted.
              Sign in to access your workspace.
            </>
          ) : (
            <>This invitation has already been accepted. Sign in to continue.</>
          )}
        </p>
        <Link href="/login">
          <Button className="mt-6 rounded-xl">
            <LogIn className="mr-2 size-4" /> Go to Login
          </Button>
        </Link>
      </div>
    );
  }

  return (
    <div className="glass-card mx-auto flex w-full max-w-md flex-col items-center rounded-2xl p-8 text-center">
      <XCircle className="mb-4 size-12 text-destructive" />
      <h1 className="text-xl font-bold">Invalid invitation</h1>
      <p className="mt-2 text-sm text-muted-foreground">
        This invitation link is invalid or no longer exists. If you believe this is a
        mistake, ask the person who invited you to send a new link.
      </p>
      <Link href="/login">
        <Button variant="outline" className="mt-6 rounded-xl">
          Go to Login
        </Button>
      </Link>
    </div>
  );
}
