"use client";

import { useState } from "react";
import Modal from "@/components/Modal";
import { useSubscriptionControllerGrantComplimentaryV1 } from "@/api/admin/admin-subscriptions/admin-subscriptions";
import { customInstance } from "@/config/axios";
import { normalizeEmail, isEmailAlreadyExistsError } from "@/lib/email";
import toast from "react-hot-toast";

type SelectableUser = {
  uuid: string;
  name?: string;
  email: string;
};

interface GrantComplimentaryModalProps {
  isOpen: boolean;
  onClose: () => void;
  /**
   * Pre-selected user (per-row grant icon flow). When null, the modal renders
   * Name + Email inputs to create a new user and grant in one atomic call.
   */
  user: SelectableUser | null;
  onGranted?: () => void;
}

type DurationOption = 1 | 3 | 6 | 12 | "lifetime";

const DURATION_OPTIONS: { value: DurationOption; label: string }[] = [
  { value: 1, label: "1 Month" },
  { value: 3, label: "3 Months" },
  { value: 6, label: "6 Months" },
  { value: 12, label: "1 Year" },
  { value: "lifetime", label: "Lifetime" },
];

const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

// Backend rule: min 8 chars + at least one upper, one lower, one number, one special.
const PASSWORD_MIN = 8;
const PASSWORD_HAS_UPPER = /[A-Z]/;
const PASSWORD_HAS_LOWER = /[a-z]/;
const PASSWORD_HAS_NUMBER = /\d/;
const PASSWORD_HAS_SPECIAL = /[^A-Za-z0-9]/;

function getPasswordError(value: string): string | null {
  if (!value) return "Password is required.";
  if (value.length < PASSWORD_MIN) return `Password must be at least ${PASSWORD_MIN} characters.`;
  if (!PASSWORD_HAS_UPPER.test(value)) return "Include at least one uppercase letter (A–Z).";
  if (!PASSWORD_HAS_LOWER.test(value)) return "Include at least one lowercase letter (a–z).";
  if (!PASSWORD_HAS_NUMBER.test(value)) return "Include at least one number (0–9).";
  if (!PASSWORD_HAS_SPECIAL.test(value)) return "Include at least one special character (e.g. !@#$).";
  return null;
}

/**
 * Grants the Therapist Manager Subscription plan to a user at no charge.
 *
 * Two flows:
 *  - Per-row icon: parent passes `user` directly → calls grant-complimentary.
 *  - Header "Grant Access" button: parent passes `user={null}` → modal shows
 *    Name + Email fields and calls /admin/users/invite with grant block to
 *    create user + complimentary subscription atomically.
 */
export default function GrantComplimentaryModal({
  isOpen,
  onClose,
  user,
  onGranted,
}: GrantComplimentaryModalProps) {
  const [reason, setReason] = useState("");
  const [duration, setDuration] = useState<DurationOption>(3);
  const [showReasonError, setShowReasonError] = useState(false);

  // New-user fields — only used when `user` prop is null
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");
  const [showPassword, setShowPassword] = useState(false);
  const [showConfirmPassword, setShowConfirmPassword] = useState(false);
  const [showNameError, setShowNameError] = useState(false);
  const [showEmailError, setShowEmailError] = useState<string | null>(null);
  const [showPasswordError, setShowPasswordError] = useState<string | null>(null);
  const [showConfirmError, setShowConfirmError] = useState<string | null>(null);

  // Loading state for the create-with-grant flow (per-row uses the mutation's isPending)
  const [isCreating, setIsCreating] = useState(false);

  const isNewUserFlow = !user;

  const { mutate, isPending } = useSubscriptionControllerGrantComplimentaryV1({
    mutation: {
      onSuccess: () => {
        toast.success("Complimentary access granted");
        resetForm();
        onClose();
        onGranted?.();
      },
      onError: (err: unknown) => {
        const message =
          (err as { response?: { data?: { message?: string } } })?.response?.data?.message ||
          "Failed to grant complimentary access";
        toast.error(message);
      },
    },
  });

  const busy = isPending || isCreating;

  const resetForm = () => {
    setReason("");
    setDuration(3);
    setShowReasonError(false);
    setName("");
    setEmail("");
    setPassword("");
    setConfirmPassword("");
    setShowPassword(false);
    setShowConfirmPassword(false);
    setShowNameError(false);
    setShowEmailError(null);
    setShowPasswordError(null);
    setShowConfirmError(null);
  };

  const validateNewUserFields = (): boolean => {
    let ok = true;
    if (!name.trim()) {
      setShowNameError(true);
      ok = false;
    }
    if (!email.trim()) {
      setShowEmailError("Email is required.");
      ok = false;
    } else if (!EMAIL_REGEX.test(email.trim())) {
      setShowEmailError("Enter a valid email address.");
      ok = false;
    }
    const pwErr = getPasswordError(password);
    if (pwErr) {
      setShowPasswordError(pwErr);
      ok = false;
    }
    if (!confirmPassword) {
      setShowConfirmError("Please confirm the password.");
      ok = false;
    } else if (confirmPassword !== password) {
      setShowConfirmError("Passwords do not match.");
      ok = false;
    }
    return ok;
  };

  const handleConfirm = async () => {
    let valid = true;

    // Reason required for both flows
    if (!reason.trim()) {
      setShowReasonError(true);
      valid = false;
    }

    // Validate new-user fields together so all errors render at once
    if (isNewUserFlow && !validateNewUserFields()) {
      valid = false;
    }

    if (!valid) return;

    if (isNewUserFlow) {
      setIsCreating(true);
      try {
        await customInstance({
          url: "/v1/admin/users/invite",
          method: "POST",
          headers: { "Content-Type": "application/json" },
          data: {
            name: name.trim(),
            email: normalizeEmail(email.trim()),
            password,
            role: "Practitioners",
            grant: {
              // null = no expiry (admin must revoke manually)
              duration_months: duration === "lifetime" ? null : duration,
              reason: reason.trim(),
            },
          },
        });
        toast.success("User invited and complimentary access granted");
        resetForm();
        onClose();
        onGranted?.();
      } catch (error: unknown) {
        if (isEmailAlreadyExistsError(error)) {
          setShowEmailError("This email is already registered.");
          return;
        }
        const err = error as { response?: { data?: { message?: string } } };
        toast.error(err?.response?.data?.message || "Failed to grant access");
      } finally {
        setIsCreating(false);
      }
      return;
    }

    // Existing-user flow
    if (!user) return;
    mutate({
      data: {
        user_uuid: user.uuid,
        reason: reason.trim(),
        // null = no expiry (admin must revoke manually)
        duration_months: duration === "lifetime" ? null : duration,
      },
    });
  };

  const handleClose = () => {
    if (busy) return;
    resetForm();
    onClose();
  };

  if (!isOpen) return null;

  return (
    <Modal isOpen={isOpen} onClose={handleClose} size="md">
      <div className="space-y-5">
        <div>
          <h2 className="text-lg font-semibold text-gray-900">
            Grant Therapist Manager Access
          </h2>
          <p className="mt-1 text-sm text-gray-500">
            User will receive the <strong>Therapist Manager Subscription</strong> plan
            for free. No Stripe charge will be made.
          </p>
        </div>

        {/* New-user fields — when no user is pre-selected */}
        {isNewUserFlow && (
          <>
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Name <span className="text-red-500">*</span>
              </label>
              <input
                type="text"
                value={name}
                onChange={(e) => {
                  setName(e.target.value);
                  if (showNameError && e.target.value.trim()) setShowNameError(false);
                }}
                onBlur={() => {
                  if (!name.trim()) setShowNameError(true);
                }}
                disabled={busy}
                placeholder="Enter Name"
                className={`w-full px-4 py-3 border rounded-full text-sm text-gray-600 placeholder-gray-400 focus:outline-none focus:ring-2 focus:border-transparent disabled:opacity-50 ${
                  showNameError
                    ? "border-red-400 focus:ring-red-400"
                    : "border-gray-200 focus:ring-emerald-500"
                }`}
              />
              {showNameError && (
                <p className="mt-1 text-xs text-red-500">Name is required.</p>
              )}
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                E-mail <span className="text-red-500">*</span>
              </label>
              <input
                type="email"
                value={email}
                onChange={(e) => {
                  setEmail(e.target.value);
                  if (showEmailError) setShowEmailError(null);
                }}
                onBlur={() => {
                  const v = email.trim();
                  if (!v) setShowEmailError("Email is required.");
                  else if (!EMAIL_REGEX.test(v)) setShowEmailError("Enter a valid email address.");
                }}
                disabled={busy}
                placeholder="Enter E-mail"
                className={`w-full px-4 py-3 border rounded-full text-sm text-gray-600 placeholder-gray-400 focus:outline-none focus:ring-2 focus:border-transparent disabled:opacity-50 ${
                  showEmailError
                    ? "border-red-400 focus:ring-red-400"
                    : "border-gray-200 focus:ring-emerald-500"
                }`}
              />
              {showEmailError && (
                <p className="mt-1 text-xs text-red-500">{showEmailError}</p>
              )}
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Set Password <span className="text-red-500">*</span>
              </label>
              <div className="relative">
                <input
                  type={showPassword ? "text" : "password"}
                  value={password}
                  onChange={(e) => {
                    setPassword(e.target.value);
                    if (showPasswordError) setShowPasswordError(null);
                    if (showConfirmError && confirmPassword === e.target.value) {
                      setShowConfirmError(null);
                    }
                  }}
                  onBlur={() => {
                    const err = getPasswordError(password);
                    if (err) setShowPasswordError(err);
                    // re-check confirm match when password loses focus
                    if (confirmPassword && confirmPassword !== password) {
                      setShowConfirmError("Passwords do not match.");
                    }
                  }}
                  disabled={busy}
                  placeholder="Min 8 chars · A-Z · a-z · 0-9 · !@#"
                  className={`w-full px-4 py-3 pr-11 border rounded-full text-sm text-gray-600 placeholder-gray-400 focus:outline-none focus:ring-2 focus:border-transparent disabled:opacity-50 ${
                    showPasswordError
                      ? "border-red-400 focus:ring-red-400"
                      : "border-gray-200 focus:ring-emerald-500"
                  }`}
                />
                <button
                  type="button"
                  onClick={() => setShowPassword((v) => !v)}
                  disabled={busy}
                  tabIndex={-1}
                  className="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 cursor-pointer disabled:opacity-50"
                  aria-label={showPassword ? "Hide password" : "Show password"}
                >
                  {showPassword ? (
                    <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                      <path strokeLinecap="round" strokeLinejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.243 4.243L9.88 9.88" />
                    </svg>
                  ) : (
                    <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                      <path strokeLinecap="round" strokeLinejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
                      <path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
                    </svg>
                  )}
                </button>
              </div>
              {showPasswordError && (
                <p className="mt-1 text-xs text-red-500">{showPasswordError}</p>
              )}
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Confirm Password <span className="text-red-500">*</span>
              </label>
              <div className="relative">
                <input
                  type={showConfirmPassword ? "text" : "password"}
                  value={confirmPassword}
                  onChange={(e) => {
                    setConfirmPassword(e.target.value);
                    if (showConfirmError && (e.target.value === password || !e.target.value)) {
                      setShowConfirmError(null);
                    }
                  }}
                  onBlur={() => {
                    if (!confirmPassword) setShowConfirmError("Please confirm the password.");
                    else if (confirmPassword !== password) setShowConfirmError("Passwords do not match.");
                  }}
                  disabled={busy}
                  placeholder="Re-enter password"
                  className={`w-full px-4 py-3 pr-11 border rounded-full text-sm text-gray-600 placeholder-gray-400 focus:outline-none focus:ring-2 focus:border-transparent disabled:opacity-50 ${
                    showConfirmError
                      ? "border-red-400 focus:ring-red-400"
                      : "border-gray-200 focus:ring-emerald-500"
                  }`}
                />
                <button
                  type="button"
                  onClick={() => setShowConfirmPassword((v) => !v)}
                  disabled={busy}
                  tabIndex={-1}
                  className="absolute right-4 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 cursor-pointer disabled:opacity-50"
                  aria-label={showConfirmPassword ? "Hide password" : "Show password"}
                >
                  {showConfirmPassword ? (
                    <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                      <path strokeLinecap="round" strokeLinejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.522 10.522 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.243 4.243L9.88 9.88" />
                    </svg>
                  ) : (
                    <svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={1.5}>
                      <path strokeLinecap="round" strokeLinejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
                      <path strokeLinecap="round" strokeLinejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
                    </svg>
                  )}
                </button>
              </div>
              {showConfirmError && (
                <p className="mt-1 text-xs text-red-500">{showConfirmError}</p>
              )}
            </div>
          </>
        )}

        {/* Pre-selected user info — per-row flow */}
        {!isNewUserFlow && user && (
          <div className="rounded-lg border border-gray-200 bg-gray-50 p-3">
            <p className="text-sm font-medium text-gray-900">{user.name || "Unknown"}</p>
            <p className="text-xs text-gray-500">{user.email}</p>
          </div>
        )}

        {/* Duration */}
        <div>
          <label className="block text-sm font-medium text-gray-700 mb-2">
            Duration
          </label>
          <div className="grid grid-cols-5 gap-2">
            {DURATION_OPTIONS.map((opt) => {
              const isNoEnd = opt.value === "lifetime";
              const isSelected = duration === opt.value;
              return (
                <button
                  key={String(opt.value)}
                  type="button"
                  onClick={() => setDuration(opt.value)}
                  disabled={busy}
                  className={`px-2 py-2 text-xs font-medium rounded-lg border transition cursor-pointer disabled:opacity-50 ${
                    isSelected
                      ? isNoEnd
                        ? "bg-amber-50 border-amber-500 text-amber-700"
                        : "bg-emerald-50 border-emerald-500 text-emerald-700"
                      : "bg-white border-gray-300 text-gray-600 hover:bg-gray-50"
                  }`}
                >
                  {opt.label}
                </button>
              );
            })}
          </div>
          {duration === "lifetime" && (
            <div className="mt-2 flex items-start gap-2 rounded-lg bg-amber-50 border border-amber-200 px-3 py-2">
              <svg
                className="w-4 h-4 mt-0.5 flex-shrink-0 text-amber-600"
                fill="none"
                viewBox="0 0 24 24"
                stroke="currentColor"
                strokeWidth={2}
              >
                <path
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"
                />
              </svg>
              <p className="text-xs text-amber-800">
                <strong>Lifetime grant</strong> — access continues until admin manually revokes.
                Use only for permanent partner accounts.
              </p>
            </div>
          )}
        </div>

        {/* Reason */}
        <div>
          <label htmlFor="grant-reason" className="block text-sm font-medium text-gray-700 mb-1">
            Reason <span className="text-red-500">*</span>
          </label>
          <textarea
            id="grant-reason"
            value={reason}
            onChange={(e) => {
              setReason(e.target.value);
              if (showReasonError && e.target.value.trim()) setShowReasonError(false);
            }}
            disabled={busy}
            placeholder="e.g. University Program, Free Clinic, VIP, Partnership"
            rows={3}
            maxLength={255}
            className={`w-full rounded-lg border px-3 py-2 text-sm focus:outline-none focus:ring-2 disabled:opacity-50 ${
              showReasonError
                ? "border-red-400 focus:ring-red-400"
                : "border-gray-300 focus:ring-emerald-500"
            }`}
          />
          {showReasonError ? (
            <p className="mt-1 text-xs text-red-500">Reason is required for audit logging.</p>
          ) : (
            <p className="mt-1 text-xs text-gray-400">
              Saved in the audit log for tracking. Max 255 characters.
            </p>
          )}
        </div>

        <div className="flex items-center justify-end gap-3 pt-2">
          <button
            type="button"
            onClick={handleClose}
            disabled={busy}
            className="px-4 py-2 text-sm font-medium text-gray-600 border border-gray-300 rounded-full hover:bg-gray-50 transition disabled:opacity-50 cursor-pointer"
          >
            Cancel
          </button>
          <button
            type="button"
            onClick={handleConfirm}
            disabled={busy}
            className="inline-flex items-center gap-2 px-5 py-2 text-sm font-medium text-white bg-emerald-600 hover:bg-emerald-700 rounded-full transition disabled:opacity-50 cursor-pointer"
          >
            {busy ? (
              <>
                <span className="w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" />
                {isNewUserFlow ? "Creating..." : "Granting..."}
              </>
            ) : (
              isNewUserFlow ? "Create & Grant Access" : "Grant Free Access"
            )}
          </button>
        </div>
      </div>
    </Modal>
  );
}
