'use client';

import React, { useState, useEffect } from 'react';
import { FiX } from 'react-icons/fi';
import toast from 'react-hot-toast';
import {
  requestDocumentOtp,
  unlockDocument,
  fetchDocumentBlob,
  downloadDocument,
} from '@/lib/api/documents.api';
import type { DocumentRow } from '@/lib/api/types/documents.types';

interface Props {
  isOpen: boolean;
  document: DocumentRow | null;
  onClose: () => void;
  /** Which action the user picked from the row — determines what runs after unlock. */
  initialMode: 'view' | 'download';
  /** True if this user has permission to download (server also checks). */
  canDownload: boolean;
}

export default function UnlockModal({
  isOpen,
  document: doc,
  onClose,
  initialMode,
  canDownload,
}: Props) {
  const [password, setPassword] = useState('');
  const [otp, setOtp] = useState('');
  const [sending, setSending] = useState(false);
  const [otpSent, setOtpSent] = useState(false);
  const [unlocking, setUnlocking] = useState(false);
  const [expiresIn, setExpiresIn] = useState<number>(0);

  // ⚠️ IMPORTANT: doc can be null (modal closed). Every hook below must run
  // on EVERY render regardless of isOpen/doc — never put a conditional
  // `return` in between hooks, or React throws a "hooks order changed"
  // crash the instant `doc` flips from null to a real document (i.e. the
  // exact moment you click "Open"). Guard the *logic inside* each hook
  // instead, and only bail out of the render (JSX) after all hooks ran.

  const needsOtp = doc?.require_otp === 1;
  const needsPassword = !!doc?.password_hash;

  useEffect(() => {
    if (isOpen) {
      // Fresh state each time the modal opens
      setPassword('');
      setOtp('');
      setSending(false);
      setOtpSent(false);
      setUnlocking(false);
      setExpiresIn(0);
    }
  }, [isOpen, doc?.id]);

  const handleRequestOtp = async () => {
    if (!doc) return;
    setSending(true);
    try {
      const res = await requestDocumentOtp(doc.id);
      setOtpSent(true);
      setExpiresIn(res.expires_in_minutes);
      toast.success(`OTP sent to your email — valid for ${res.expires_in_minutes} min`);
    } catch (err: any) {
      toast.error(err.message || 'Failed to send OTP');
    } finally {
      setSending(false);
    }
  };

  const handleUnlock = async () => {
    if (!doc) return;
    if (needsPassword && !password) return toast.error('Password required');
    if (needsOtp && (!otp || otp.length < 4)) return toast.error('OTP required');

    setUnlocking(true);
    try {
      const res = await unlockDocument(doc.id, {
        password: needsPassword ? password : undefined,
        otp: needsOtp ? otp : undefined,
      });

      // Actually open / download
      if (initialMode === 'download' && canDownload && res.download_url) {
        await downloadDocument(doc.id, res.token, doc.file_name);
        toast.success('Download started');
      } else {
        const blobUrl = await fetchDocumentBlob(doc.id, res.token, 'view');
        // Open in a new tab so the user can preview the PDF/image inline.
        window.open(blobUrl, '_blank', 'noopener');
      }

      onClose();
    } catch (err: any) {
      toast.error(err.message || 'Unlock failed');
      // Clear OTP so the user can re-enter — password field kept.
      setOtp('');
    } finally {
      setUnlocking(false);
    }
  };

  // If no security is required, just unlock immediately on mount.
  useEffect(() => {
    if (isOpen && doc && !needsPassword && !needsOtp && !unlocking) {
      handleUnlock();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isOpen, doc?.id]);

  // ✅ Safe to bail out of rendering now — every hook above already ran
  // on this render, so hook order/count stays identical every time.
  if (!isOpen || !doc) return null;

  return (
    <div style={overlayStyle} onClick={unlocking ? undefined : onClose}>
      <div style={modalStyle} onClick={(e) => e.stopPropagation()}>
        <button onClick={onClose} disabled={unlocking} style={closeBtnStyle}>
          <FiX size={20} />
        </button>

        <div style={{ fontSize: 42, textAlign: 'center', marginBottom: 6 }}>🔒</div>
        <h3 style={{ fontSize: 18, textAlign: 'center', margin: '0 0 3px', color: '#1a0440' }}>
          Protected Document
        </h3>
        <p style={{ fontSize: 12, textAlign: 'center', color: '#8b8397', margin: '0 0 20px' }}>
          {doc.title}
        </p>

        {needsPassword && (
          <div style={{ marginBottom: 14 }}>
            <label style={labelStyle}>Document password</label>
            <input
              type="password"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              placeholder="Enter password"
              style={inputStyle}
              autoFocus
              disabled={unlocking}
            />
          </div>
        )}

        {needsOtp && (
          <div style={{ marginBottom: 14 }}>
            <label style={labelStyle}>
              Email OTP{' '}
              {otpSent && (
                <span style={{ color: '#7c3aed', fontWeight: 700 }}>
                  (sent — valid {expiresIn} min)
                </span>
              )}
            </label>
            <div style={{ display: 'flex', gap: 8, alignItems: 'stretch' }}>
              <input
                type="text"
                inputMode="numeric"
                value={otp}
                onChange={(e) => setOtp(e.target.value.replace(/\D/g, '').slice(0, 6))}
                placeholder="6-digit code"
                style={{ ...inputStyle, letterSpacing: '0.3em', fontFamily: 'monospace' }}
                disabled={unlocking}
                autoFocus={!needsPassword}
              />
              <button
                onClick={handleRequestOtp}
                disabled={sending || unlocking}
                style={secondaryBtnStyle}
              >
                {sending ? 'Sending…' : otpSent ? 'Resend' : 'Send OTP'}
              </button>
            </div>
          </div>
        )}

        <button
          onClick={handleUnlock}
          disabled={unlocking || (needsOtp && !otpSent && !otp)}
          style={{
            ...primaryBtnStyle,
            width: '100%',
            justifyContent: 'center',
            marginTop: 6,
            opacity: unlocking || (needsOtp && !otpSent && !otp) ? 0.6 : 1,
          }}
        >
          {unlocking
            ? 'Verifying…'
            : initialMode === 'download'
              ? 'Unlock & Download'
              : 'Unlock & View'}
        </button>

        <p
          onClick={unlocking ? undefined : onClose}
          style={{
            fontSize: 11,
            color: '#94a3b8',
            marginTop: 10,
            cursor: unlocking ? 'not-allowed' : 'pointer',
            textAlign: 'center',
          }}
        >
          Cancel
        </p>
      </div>
    </div>
  );
}

const overlayStyle: React.CSSProperties = {
  position: 'fixed',
  inset: 0,
  background: 'rgba(15,23,42,0.55)',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'center',
  zIndex: 1000,
  padding: 16,
};
const modalStyle: React.CSSProperties = {
  background: '#fff',
  borderRadius: 16,
  width: '100%',
  maxWidth: 400,
  padding: '28px 26px 22px',
  boxShadow: '0 24px 48px -12px rgba(0,0,0,0.3)',
  position: 'relative',
};
const closeBtnStyle: React.CSSProperties = {
  position: 'absolute',
  top: 12,
  right: 12,
  background: 'none',
  border: 'none',
  color: '#8b8397',
  cursor: 'pointer',
  padding: 4,
};
const labelStyle: React.CSSProperties = {
  fontSize: 10,
  fontWeight: 800,
  color: '#94a3b8',
  textTransform: 'uppercase',
  letterSpacing: '0.06em',
  marginBottom: 6,
  display: 'block',
};
const inputStyle: React.CSSProperties = {
  width: '100%',
  border: '1.5px solid #eae5f1',
  borderRadius: 10,
  padding: '10px 13px',
  fontSize: 13,
  outline: 'none',
  background: '#fcfbfe',
  fontFamily: 'inherit',
  color: '#26203a',
};
const primaryBtnStyle: React.CSSProperties = {
  padding: '11px 22px',
  borderRadius: 11,
  border: 'none',
  background: 'linear-gradient(135deg, #7c3aed, #4a0080)',
  color: '#fff',
  fontSize: 13,
  fontWeight: 700,
  cursor: 'pointer',
  display: 'inline-flex',
  alignItems: 'center',
  gap: 8,
  boxShadow: '0 10px 22px -12px rgba(74,0,128,0.6)',
};
const secondaryBtnStyle: React.CSSProperties = {
  padding: '10px 14px',
  borderRadius: 10,
  border: '1.5px solid #eae5f1',
  background: '#fff',
  color: '#7c3aed',
  fontSize: 12,
  fontWeight: 700,
  cursor: 'pointer',
  whiteSpace: 'nowrap',
};