import { json, redirect, type ActionFunctionArgs, type LoaderFunctionArgs } from "@remix-run/node";
import { Form, useActionData, useLoaderData, useNavigation } from "@remix-run/react";
import bcrypt from "bcryptjs";
import crypto from "crypto";
import { sendNotificationEmail } from "~/utils/mail.server";
import { prisma } from "~/utils/db.server";

export async function loader({ request }: LoaderFunctionArgs) {
  const url = new URL(request.url);
  const token = url.searchParams.get("token");
  
  if (!token) {
    return json({ showEmailForm: true, token: null, error: null });
  }
  
  // Check if token is valid
  const resetToken = await prisma.passwordResetToken.findUnique({
    where: { token },
    include: { employee: true }
  });
  
  if (!resetToken) {
    return json({ 
      showEmailForm: false, 
      token: null, 
      error: "Invalid reset token. Please request a new password reset." 
    });
  }
  
  if (resetToken.used) {
    return json({ 
      showEmailForm: false, 
      token: null, 
      error: "This reset token has already been used. Please request a new password reset." 
    });
  }
  
  if (new Date() > resetToken.expiresAt) {
    return json({ 
      showEmailForm: false, 
      token: null, 
      error: "This reset token has expired. Please request a new password reset." 
    });
  }
  
  return json({ 
    showEmailForm: false, 
    token, 
    error: null,
    employeeName: resetToken.employee.name
  });
}

export async function action({ request }: ActionFunctionArgs) {
  const formData = await request.formData();
  const intent = formData.get("intent");
  
  if (intent === "send-reset-email") {
    const email = formData.get("email")?.toString();
    
    if (!email) {
      return json({ error: "Email is required" }, { status: 400 });
    }
    
    // Find employee by email
    const employee = await prisma.employee.findUnique({
      where: { email }
    });
    
    if (!employee) {
      // Don't reveal if email exists or not for security
      return json({ 
        success: true, 
        message: "If an account with this email exists, you will receive a password reset link." 
      });
    }
    
    // Generate reset token
    const token = crypto.randomBytes(32).toString("hex");
    const expiresAt = new Date(Date.now() + 60 * 60 * 1000); // 1 hour from now
    
    // Save token to database
    await prisma.passwordResetToken.create({
      data: {
        token,
        employeeId: employee.id,
        expiresAt
      }
    });
    
    // Send reset email
    const resetUrl = `${new URL(request.url).origin}/reset-password?token=${token}`;
    const emailResult = await sendNotificationEmail(
      employee.email,
      "Password Reset Request",
      `Hello ${employee.name},\n\nYou requested a password reset. Click the link below to reset your password:\n\n${resetUrl}\n\nThis link will expire in 1 hour.\n\nIf you didn't request this, please ignore this email.`,
      false
    );
    
    if (!emailResult.success) {
      return json({ error: "Failed to send reset email. Please try again." }, { status: 500 });
    }
    
    return json({ 
      success: true, 
      message: "If an account with this email exists, you will receive a password reset link." 
    });
  }
  
  if (intent === "reset-password") {
    const token = formData.get("token")?.toString();
    const password = formData.get("password")?.toString();
    const confirmPassword = formData.get("confirmPassword")?.toString();
    
    if (!token || !password || !confirmPassword) {
      return json({ error: "All fields are required" }, { status: 400 });
    }
    
    if (password !== confirmPassword) {
      return json({ error: "Passwords do not match" }, { status: 400 });
    }
    
    if (password.length < 6) {
      return json({ error: "Password must be at least 6 characters long" }, { status: 400 });
    }
    
    // Verify token again
    const resetToken = await prisma.passwordResetToken.findUnique({
      where: { token },
      include: { employee: true }
    });
    
    if (!resetToken || resetToken.used || new Date() > resetToken.expiresAt) {
      return json({ error: "Invalid or expired token" }, { status: 400 });
    }
    
    // Hash new password
    const hashedPassword = await bcrypt.hash(password, 10);
    
    // Update password and mark token as used
    await prisma.$transaction([
      prisma.employee.update({
        where: { id: resetToken.employeeId },
        data: { password: hashedPassword }
      }),
      prisma.passwordResetToken.update({
        where: { id: resetToken.id },
        data: { used: true }
      })
    ]);
    
    return redirect("/signin?message=Password reset successful. Please sign in with your new password.");
  }
  
  return json({ error: "Invalid request" }, { status: 400 });
}

export default function ResetPassword() {
  const loaderData = useLoaderData<typeof loader>();
  const actionData = useActionData<typeof action>();
  const navigation = useNavigation();
  const isSubmitting = navigation.state === "submitting";
  
  if (loaderData.error) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
        <div className="max-w-md w-full space-y-8">
          <div className="text-center">
            <h2 className="mt-6 text-3xl font-extrabold text-gray-900">
              Password Reset Error
            </h2>
            <div className="mt-4 p-4 bg-red-50 border border-red-200 rounded-md">
              <p className="text-red-800">{loaderData.error}</p>
            </div>
            <div className="mt-4">
              <a
                href="/reset-password"
                className="text-indigo-600 hover:text-indigo-500 font-medium"
              >
                Request a new password reset
              </a>
            </div>
          </div>
        </div>
      </div>
    );
  }
  
  if (loaderData.showEmailForm) {
    return (
      <div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
        <div className="max-w-md w-full space-y-8">
          <div>
            <h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
              Reset your password
            </h2>
            <p className="mt-2 text-center text-sm text-gray-600">
              Enter your email address and we'll send you a link to reset your password.
            </p>
          </div>
          
          {actionData?.error && (
            <div className="p-4 bg-red-50 border border-red-200 rounded-md">
              <p className="text-red-800">{actionData.error}</p>
            </div>
          )}
          
          {actionData?.success && (
            <div className="p-4 bg-green-50 border border-green-200 rounded-md">
              <p className="text-green-800">{actionData.message}</p>
            </div>
          )}
          
          <Form method="post" className="mt-8 space-y-6">
            <input type="hidden" name="intent" value="send-reset-email" />
            <div>
              <label htmlFor="email" className="sr-only">
                Email address
              </label>
              <input
                id="email"
                name="email"
                type="email"
                autoComplete="email"
                required
                className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
                placeholder="Email address"
              />
            </div>
            
            <div>
              <button
                type="submit"
                disabled={isSubmitting}
                className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50"
              >
                {isSubmitting ? "Sending..." : "Send reset link"}
              </button>
            </div>
            
            <div className="text-center">
              <a
                href="/signin"
                className="text-indigo-600 hover:text-indigo-500 font-medium"
              >
                Back to sign in
              </a>
            </div>
          </Form>
        </div>
      </div>
    );
  }
  
  // Show password reset form
  return (
    <div className="min-h-screen flex items-center justify-center bg-gray-50 py-12 px-4 sm:px-6 lg:px-8">
      <div className="max-w-md w-full space-y-8">
        <div>
          <h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
            Set new password
          </h2>
          <p className="mt-2 text-center text-sm text-gray-600">
            {loaderData.employeeName && `Hello ${loaderData.employeeName}, `}
            Enter your new password below.
          </p>
        </div>
        
        {actionData?.error && (
          <div className="p-4 bg-red-50 border border-red-200 rounded-md">
            <p className="text-red-800">{actionData.error}</p>
          </div>
        )}
        
        <Form method="post" className="mt-8 space-y-6">
          <input type="hidden" name="intent" value="reset-password" />
          <input type="hidden" name="token" value={loaderData.token} />
          
          <div className="space-y-4">
            <div>
              <label htmlFor="password" className="sr-only">
                New Password
              </label>
              <input
                id="password"
                name="password"
                type="password"
                autoComplete="new-password"
                required
                minLength={6}
                className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
                placeholder="New password (min 6 characters)"
              />
            </div>
            
            <div>
              <label htmlFor="confirmPassword" className="sr-only">
                Confirm Password
              </label>
              <input
                id="confirmPassword"
                name="confirmPassword"
                type="password"
                autoComplete="new-password"
                required
                minLength={6}
                className="appearance-none rounded-md relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 focus:z-10 sm:text-sm"
                placeholder="Confirm new password"
              />
            </div>
          </div>
          
          <div>
            <button
              type="submit"
              disabled={isSubmitting}
              className="group relative w-full flex justify-center py-2 px-4 border border-transparent text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50"
            >
              {isSubmitting ? "Updating..." : "Update password"}
            </button>
          </div>
        </Form>
      </div>
    </div>
  );
}