'use client';

import { useEffect, useRef, useState } from 'react';
import { usePathname } from 'next/navigation';
import Cookies from 'js-cookie';
import { api, NetworkError } from '@/lib/api';

/** Retries for a check that never reached the server (see checkStatus below). */
const NETWORK_RETRIES = 2;
const RETRY_DELAY_MS = 1200;
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

export default function PasswordExpiryGuard({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();
  const [profile, setProfile] = useState<any>(null);
  const [loading, setLoading] = useState(true);
  const [expiredModalOpen, setExpiredModalOpen] = useState(false);
  const [reminder, setReminder] = useState<string | null>(null);

  // Form states
  const [currentPassword, setCurrentPassword] = useState('');
  const [newPassword, setNewPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [showCurrentPassword, setShowCurrentPassword] = useState(false);
  const [showNewPassword, setShowNewPassword] = useState(false);
  const [showConfirmPassword, setShowConfirmPassword] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [apiError, setApiError] = useState('');
  const [successExpiry, setSuccessExpiry] = useState<string | null>(null);

  // Latch so the expiry/reminder check runs ONLY ONCE per login session and not
  // again on every client-side navigation. This guard stays mounted across route
  // changes (it's in the root layout), so a ref is enough: it survives navigations
  // but resets on a full page reload (remount) — which re-enforces the hard block —
  // and we clear it whenever the user returns to /login (a new session boundary).
  const checkedThisSessionRef = useRef(false);

  useEffect(() => {
    // /login marks a session boundary: reset the latch so the next login re-checks,
    // and clear any lingering modal/reminder state from the previous session.
    if (pathname === '/login') {
      checkedThisSessionRef.current = false;
      setExpiredModalOpen(false);
      setReminder(null);
      setLoading(false);
      return;
    }

    const token = Cookies.get('access_token');
    if (!token) {
      setLoading(false);
      return;
    }

    // Already checked this session — do not re-fetch or re-open on navigation.
    // Also blocks React Strict Mode's double-invoke from firing a second request.
    if (checkedThisSessionRef.current) {
      setLoading(false);
      return;
    }
    checkedThisSessionRef.current = true;

    // Fetch profile and check password expiry.
    //
    // A NetworkError means the request never reached the server — in practice a
    // backend restart (the dev server reloads on every .py save) or a momentary
    // blip, not a real failure. Both calls here are GETs, so retrying is safe and
    // cannot double-submit anything. Only NetworkError is retried; a real HTTP
    // error (401/403/500) is reported on the first attempt as before.
    async function checkStatus() {
      for (let attempt = 0; ; attempt++) {
        try {
          const userProfile = await api.get('/users/profile/') as any;
          setProfile(userProfile.data);

          if (userProfile.data.password_expired) {
            setExpiredModalOpen(true);
          } else {
            // Check reminder status
            const reminderRes = await api.get('/auth/password/reminder-status/') as any;
            if (reminderRes.data.show_reminder) {
              setReminder(reminderRes.data.message);
            }
          }
          setLoading(false);
          return;
        } catch (err) {
          if (err instanceof NetworkError && attempt < NETWORK_RETRIES) {
            await wait(RETRY_DELAY_MS);
            continue;   // backend probably still coming back up
          }
          // Let a failed check retry on the next reload rather than staying latched.
          checkedThisSessionRef.current = false;
          console.error('Failed to fetch profile or password expiry status:', err);
          setLoading(false);
          return;
        }
      }
    }

    checkStatus();
  }, [pathname]);

  if (pathname === '/login') {
    return <>{children}</>;
  }

  if (loading) {
    return (
      <div className="flex h-screen w-screen items-center justify-center bg-slate-50 dark:bg-slate-950">
        
      </div>
    );
  }

  // Real-time validations
  const lengthValid = newPassword.length >= 8 && newPassword.length <= 64;
  const hasUpper = /[A-Z]/.test(newPassword);
  const hasLower = /[a-z]/.test(newPassword);
  const hasDigit = /\d/.test(newPassword);
  const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(newPassword);
  const matchesConfirm = newPassword && newPassword === confirmPassword;
  const notSameAsCurrent = newPassword && newPassword !== currentPassword;
  
  const allValid = lengthValid && hasUpper && hasLower && hasDigit && hasSpecial && matchesConfirm && notSameAsCurrent;

  const handleUpdatePassword = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!allValid) return;

    setSubmitting(true);
    setApiError('');

    try {
      const res = await api.post('/auth/password/change/', {
        current_password: currentPassword,
        new_password: newPassword,
        confirm_password: confirmPassword,
      }) as any;

      setSuccessExpiry(res.data.next_expiry_date);

      // After 3 seconds: clear cookies and redirect to login for a fresh session
      setTimeout(() => {
        Cookies.remove('access_token');
        Cookies.remove('refresh_token');
        window.location.href = '/login';
      }, 3000);

    } catch (err: any) {
      setApiError(err.message || 'Failed to update password.');
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <>
      {/* Expiry Modal */}
      {expiredModalOpen && (
        <div className="fixed inset-0 z-[500] flex items-center justify-center bg-slate-900/70 dark:bg-slate-950/85 backdrop-blur-2xl p-4 overflow-y-auto">
          <div className="bg-white/90 dark:bg-slate-900/90 border border-slate-200/50 dark:border-slate-800/50 rounded-none shadow-2xl p-6 sm:p-8 max-w-md w-full backdrop-blur-xl animate-in zoom-in-95 duration-200 space-y-6 my-8">
            
            {successExpiry ? (
              <div className="text-center space-y-4 animate-in fade-in duration-300">
                <div className="w-16 h-16 bg-emerald-100 dark:bg-emerald-950/40 text-emerald-600 dark:text-emerald-400 rounded-full flex items-center justify-center text-3xl mx-auto font-bold">
                  ✓
                </div>
                <h3 className="text-xl font-extrabold text-slate-900 dark:text-white">
                  Password Updated
                </h3>
                <div className="p-4 bg-emerald-50 dark:bg-emerald-950/20 border border-emerald-100 dark:border-emerald-900/30 rounded-none">
                  <p className="text-sm font-semibold text-emerald-800 dark:text-emerald-300">
                    Password updated successfully.
                  </p>
                  <p className="text-xs text-slate-500 dark:text-slate-400 mt-2">
                    Your next password expiry date is:
                  </p>
                  <p className="text-base font-black text-slate-900 dark:text-white mt-1">
                    {successExpiry}
                  </p>
                </div>
                <p className="text-xs text-slate-400 dark:text-slate-500">
                  Redirecting back to dashboard...
                </p>
              </div>
            ) : (
              <form onSubmit={handleUpdatePassword} className="space-y-5">
                <div className="text-center space-y-2">
                  <div className="w-12 h-12 bg-amber-100 dark:bg-amber-955/40 text-amber-600 dark:text-amber-400 rounded-full flex items-center justify-center text-2xl mx-auto">
                    ⚠️
                  </div>
                  <h3 className="text-lg font-black text-slate-900 dark:text-white">
                    Password Expired
                  </h3>
                  <p className="text-xs text-slate-500 dark:text-slate-400">
                    For security reasons, your password has expired. You must create a new password before continuing.
                  </p>
                </div>

                {apiError && (
                  <div className="p-3.5 bg-rose-50 dark:bg-rose-955/20 border border-rose-100 dark:border-rose-900/30 text-rose-600 dark:text-rose-400 rounded-none text-xs font-bold leading-normal">
                    {apiError}
                  </div>
                )}

                <div className="space-y-4">
                  <div className="space-y-1">
                    <label className="block text-[10px] uppercase font-extrabold tracking-wider text-slate-400">
                      Current Password
                    </label>
                    <div className="relative">
                      <input
                        type={showCurrentPassword ? 'text' : 'password'}
                        required
                        value={currentPassword}
                        onChange={(e) => setCurrentPassword(e.target.value)}
                        placeholder="••••••••"
                        className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-none pl-3.5 pr-10 py-2 text-xs focus:outline-none focus:ring-2 focus:ring-indigo-500/20 text-slate-900 dark:text-white"
                      />
                      <button
                        type="button"
                        onClick={() => setShowCurrentPassword((s) => !s)}
                        className="absolute right-2.5 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600 transition p-1 cursor-pointer"
                        title={showCurrentPassword ? 'Hide password' : 'Show password'}
                        aria-label={showCurrentPassword ? 'Hide password' : 'Show password'}
                      >
                        <i className={`fa-solid ${showCurrentPassword ? 'fa-eye-slash' : 'fa-eye'} text-xs`}></i>
                      </button>
                    </div>
                  </div>

                  <div className="space-y-1">
                    <label className="block text-[10px] uppercase font-extrabold tracking-wider text-slate-400">
                      New Password
                    </label>
                    <div className="relative">
                      <input
                        type={showNewPassword ? 'text' : 'password'}
                        required
                        value={newPassword}
                        onChange={(e) => setNewPassword(e.target.value)}
                        placeholder="••••••••"
                        className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-none pl-3.5 pr-10 py-2 text-xs focus:outline-none focus:ring-2 focus:ring-indigo-500/20 text-slate-900 dark:text-white"
                      />
                      <button
                        type="button"
                        onClick={() => setShowNewPassword((s) => !s)}
                        className="absolute right-2.5 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600 transition p-1 cursor-pointer"
                        title={showNewPassword ? 'Hide password' : 'Show password'}
                        aria-label={showNewPassword ? 'Hide password' : 'Show password'}
                      >
                        <i className={`fa-solid ${showNewPassword ? 'fa-eye-slash' : 'fa-eye'} text-xs`}></i>
                      </button>
                    </div>
                  </div>

                  <div className="space-y-1">
                    <label className="block text-[10px] uppercase font-extrabold tracking-wider text-slate-400">
                      Confirm Password
                    </label>
                    <div className="relative">
                      <input
                        type={showConfirmPassword ? 'text' : 'password'}
                        required
                        value={confirmPassword}
                        onChange={(e) => setConfirmPassword(e.target.value)}
                        placeholder="••••••••"
                        className="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-none pl-3.5 pr-10 py-2 text-xs focus:outline-none focus:ring-2 focus:ring-indigo-500/20 text-slate-900 dark:text-white"
                      />
                      <button
                        type="button"
                        onClick={() => setShowConfirmPassword((s) => !s)}
                        className="absolute right-2.5 top-1/2 -translate-y-1/2 text-slate-400 hover:text-slate-600 transition p-1 cursor-pointer"
                        title={showConfirmPassword ? 'Hide password' : 'Show password'}
                        aria-label={showConfirmPassword ? 'Hide password' : 'Show password'}
                      >
                        <i className={`fa-solid ${showConfirmPassword ? 'fa-eye-slash' : 'fa-eye'} text-xs`}></i>
                      </button>
                    </div>
                  </div>
                </div>

                {/* Validation Indicators — horizontal wrap */}
                <div className="bg-slate-50 dark:bg-slate-955/60 rounded-none px-3 py-2.5 border border-slate-150 dark:border-slate-850">
                  <p className="text-[9px] uppercase tracking-wider font-extrabold text-slate-400 mb-2">
                    Requirements:
                  </p>
                  <div className="flex flex-wrap gap-x-4 gap-y-1">
                    {[
                      [lengthValid,      '8-64 chars'],
                      [hasUpper,         'Uppercase'],
                      [hasLower,         'Lowercase'],
                      [hasDigit,         'Number'],
                      [hasSpecial,       'Special char'],
                      [notSameAsCurrent, 'New password'],
                      [matchesConfirm,   'Passwords match'],
                    ].map(([valid, label]) => (
                      <span key={label as string} className={`flex items-center gap-1 text-[10px] font-semibold ${valid ? 'text-emerald-600 dark:text-emerald-400' : 'text-slate-400'}`}>
                        <span>{valid ? '✓' : '·'}</span>
                        {label as string}
                      </span>
                    ))}
                  </div>
                </div>

                <button
                  type="submit"
                  disabled={!allValid || submitting}
                  className="w-full bg-indigo-600 hover:bg-indigo-700 disabled:opacity-50 text-white rounded-none py-2.5 text-xs font-extrabold shadow-md shadow-indigo-600/10 transition cursor-pointer flex items-center justify-center gap-2"
                >
                  {submitting ? (
                    <>
                      
                      Updating Password...
                    </>
                  ) : (
                    'Update Password'
                  )}
                </button>
              </form>
            )}
          </div>
        </div>
      )}

      {/* Reminder Banner/Notification */}
      {reminder && (
        <div className="fixed bottom-5 right-5 z-40 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-none shadow-xl p-4 max-w-sm backdrop-blur-md animate-in slide-in-from-bottom-5 duration-300 flex items-start gap-3">
          <div className="text-amber-500 text-lg mt-0.5 shrink-0">⚠️</div>
          <div className="space-y-1.5 min-w-0">
            <h4 className="text-xs font-black text-slate-900 dark:text-white uppercase tracking-wider">
              Password Expiry Reminder
            </h4>
            <p className="text-xs text-slate-600 dark:text-slate-400 leading-normal">
              {reminder}
            </p>
            <div className="flex gap-2.5 pt-1">
              <button
                onClick={() => {
                  setExpiredModalOpen(true);
                }}
                className="text-[10px] font-extrabold text-indigo-600 dark:text-indigo-400 hover:underline cursor-pointer"
              >
                Change Now
              </button>
              <button
                onClick={() => setReminder(null)}
                className="text-[10px] font-extrabold text-slate-400 hover:text-slate-600 cursor-pointer"
              >
                Dismiss
              </button>
            </div>
          </div>
        </div>
      )}

      {children}
    </>
  );
}
