'use client';

import { Suspense, useState, useSyncExternalStore } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { toast } from 'sonner';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { BrandedAuthShell } from '@/components/shared/branded-auth-shell';

const MIN_LENGTH = 9;

const passwordSchema = z
  .object({
    password: z.string().min(MIN_LENGTH, `Must be at least ${MIN_LENGTH} characters`),
    confirmPassword: z.string().min(1, 'Please confirm your password'),
  })
  .refine((data) => data.password === data.confirmPassword, {
    message: 'Passwords do not match',
    path: ['confirmPassword'],
  });

type SetPasswordFormData = z.infer<typeof passwordSchema>;

/**
 * H-03: tokens travel in the URL fragment (`#token=…`) so they never land
 * in HTTP access logs or HTTP-Referer headers. Pre-fragment links still
 * carry `?token=…` and stay functional until every outstanding invite
 * expires - drop the `?token=` fallback after that grace period.
 */
function readTokenFromUrl(): string {
  if (typeof window === 'undefined') return '';
  const hash = window.location.hash.replace(/^#/, '');
  if (hash) {
    const params = new URLSearchParams(hash);
    const fromFragment = params.get('token');
    if (fromFragment) return fromFragment;
  }
  const search = new URLSearchParams(window.location.search);
  return search.get('token') ?? '';
}

const subscribeNoop = () => () => undefined;

function SetPasswordInner() {
  const router = useRouter();
  // useSyncExternalStore so the fragment-only token is read post-hydration
  // (server snapshot returns null; client returns the actual value).
  const token = useSyncExternalStore<string | null>(
    subscribeNoop,
    () => readTokenFromUrl(),
    () => null,
  );
  const [isLoading, setIsLoading] = useState(false);

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<SetPasswordFormData>({
    resolver: zodResolver(passwordSchema),
  });

  async function onSubmit(data: SetPasswordFormData) {
    if (!token) {
      toast.error('Invalid or missing reset token. Please request a new link.');
      return;
    }

    setIsLoading(true);
    try {
      const response = await fetch('/api/auth/set-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token, password: data.password }),
      });

      if (!response.ok) {
        const body = (await response.json().catch(() => ({}))) as {
          message?: string;
          error?: string;
        };
        toast.error(body.message ?? body.error ?? 'Failed to set password. Please try again.');
        return;
      }

      toast.success('Password set successfully. You can now sign in.');
      router.push('/login');
    } catch {
      toast.error('Something went wrong. Please try again.');
    } finally {
      setIsLoading(false);
    }
  }

  // Pre-hydration: token is null. Show a loading placeholder so the user
  // doesn't see a flash of "Link is missing" while the fragment is being
  // read on the client.
  if (token === null) {
    return (
      <BrandedAuthShell>
        <div role="status" aria-live="polite" className="text-center text-sm text-gray-500">
          Loading…
        </div>
      </BrandedAuthShell>
    );
  }

  if (!token) {
    return (
      <BrandedAuthShell>
        <div className="text-center space-y-3">
          <h1 className="text-xl font-semibold text-gray-900">Link is missing or invalid</h1>
          <p className="text-sm text-gray-500">
            Please use the link from the email we sent you. If the link is broken, ask your
            administrator for a new one.
          </p>
          <Link
            href="/login"
            className="inline-block text-sm text-[#0058b3] underline-offset-2 underline hover:no-underline"
          >
            Back to sign in
          </Link>
        </div>
      </BrandedAuthShell>
    );
  }

  return (
    <BrandedAuthShell>
      <div className="text-center mb-6">
        <h1 className="text-xl font-semibold text-gray-900">Set your password</h1>
        <p className="text-sm text-gray-500 mt-1">Choose a password for your CRM account</p>
      </div>

      <form onSubmit={handleSubmit(onSubmit)} className="space-y-4" noValidate>
        <div className="space-y-1.5">
          <Label htmlFor="password">New password</Label>
          <Input
            id="password"
            type="password"
            autoComplete="new-password"
            disabled={isLoading}
            aria-describedby="password-hint"
            className={cn(errors.password && 'border-destructive focus-visible:ring-destructive')}
            {...register('password')}
          />
          <p id="password-hint" className="text-xs text-gray-500">
            At least {MIN_LENGTH} characters.
          </p>
          {errors.password && <p className="text-sm text-destructive">{errors.password.message}</p>}
        </div>

        <div className="space-y-1.5">
          <Label htmlFor="confirmPassword">Confirm password</Label>
          <Input
            id="confirmPassword"
            type="password"
            autoComplete="new-password"
            disabled={isLoading}
            className={cn(
              errors.confirmPassword && 'border-destructive focus-visible:ring-destructive',
            )}
            {...register('confirmPassword')}
          />
          {errors.confirmPassword && (
            <p className="text-sm text-destructive">{errors.confirmPassword.message}</p>
          )}
        </div>

        <Button
          type="submit"
          className="w-full bg-[#007bff] hover:bg-[#0069d9] text-white"
          disabled={isLoading}
        >
          {isLoading ? 'Setting password…' : 'Set password'}
        </Button>
      </form>
    </BrandedAuthShell>
  );
}

export default function SetPasswordPage() {
  return (
    <Suspense fallback={<BrandedAuthShell>{null}</BrandedAuthShell>}>
      <SetPasswordInner />
    </Suspense>
  );
}
