"use client";

import { useEffect, useMemo, useRef, useState } from "react";
import { createPortal } from "react-dom";
import {
  defaultCountries,
  FlagImage,
  parseCountry,
  usePhoneInput,
  type CountryIso2,
} from "react-international-phone";
import "react-international-phone/style.css";
import type { Control, FieldValues, Path } from "react-hook-form";
import { Controller } from "react-hook-form";

interface PhoneValue {
  dialCode: string;
  number: string;
}

interface PhoneInputProps<T extends FieldValues> {
  label?: string;
  name: Path<T>;
  control: Control<T>;
  error?: string;
  placeholder?: string;
  required?: boolean;
}

export default function CustomPhoneInput<T extends FieldValues>({
  label,
  name,
  control,
  error,
  placeholder = "Enter Your Phone Number",
  required = false,
}: PhoneInputProps<T>) {
  return (
    <div className="flex flex-col gap-1">
      {label && (
        <label className="text-sm font-medium text-heading">
          {label}
          {required && <span className="ml-1 text-danger">*</span>}
        </label>
      )}

      <Controller
        name={name}
        control={control}
        render={({ field }) => (
          <PhoneFieldWithSearch
            value={field.value as PhoneValue | undefined}
            onChange={field.onChange}
            placeholder={placeholder}
            hasError={!!error}
          />
        )}
      />

      {error && <span className="text-xs text-danger">{error}</span>}
    </div>
  );
}

function PhoneFieldWithSearch({
  value,
  onChange,
  placeholder,
  hasError,
}: {
  value?: PhoneValue;
  onChange: (val: PhoneValue) => void;
  placeholder?: string;
  hasError?: boolean;
}) {
  const { inputValue, handlePhoneValueChange, inputRef, country, setCountry } =
    usePhoneInput({
      defaultCountry: "us",
      value: value ? `${value.dialCode}${value.number}` : "",
      countries: defaultCountries,
      disableDialCodeAndPrefix: true,
      onChange: (data) => {
        onChange({
          dialCode: `+${data.country.dialCode}`,
          number: data.phone.replace(`+${data.country.dialCode}`, ""),
        });
      },
    });

  const [open, setOpen] = useState(false);
  const [search, setSearch] = useState("");
  const wrapperRef = useRef<HTMLDivElement>(null);
  const buttonRef = useRef<HTMLButtonElement>(null);
  const searchInputRef = useRef<HTMLInputElement>(null);
  const portalRef = useRef<HTMLDivElement>(null);
  const [dropdownPosition, setDropdownPosition] = useState<{
    top: number;
    left: number;
    width: number;
    isAbove: boolean;
  } | null>(null);

  // Calculate dropdown position
  const calculatePosition = () => {
    if (open && buttonRef.current && wrapperRef.current) {
      const buttonRect = buttonRef.current.getBoundingClientRect();

      const viewportHeight = window.innerHeight;
      const dropdownHeight = 300; // approximate height
      const gap = 6;

      // Check if there's enough space below
      const spaceBelow = viewportHeight - buttonRect.bottom;
      const isAbove = spaceBelow < dropdownHeight;

      const top = isAbove
        ? buttonRect.top - dropdownHeight - gap // Position above
        : buttonRect.bottom + gap; // Position below

      setDropdownPosition({
        top,
        left: buttonRect.left,
        width: buttonRect.width,
        isAbove,
      });
    }
  };

  // Calculate position on open
  useEffect(() => {
    calculatePosition();
  }, [open]);

  // Recalculate position on scroll and resize
  useEffect(() => {
    if (!open) return;

    const handleScroll = () => calculatePosition();
    const handleResize = () => calculatePosition();

    window.addEventListener("scroll", handleScroll, true);
    window.addEventListener("resize", handleResize);

    return () => {
      window.removeEventListener("scroll", handleScroll, true);
      window.removeEventListener("resize", handleResize);
    };
  }, [open]);

  // Focus search input when dropdown opens
  useEffect(() => {
    if (open) {
      const id = setTimeout(() => searchInputRef.current?.focus(), 0);
      return () => clearTimeout(id);
    }
  }, [open]);

  // Close dropdown on outside click (but not on portal)
  useEffect(() => {
    function handleClickOutside(e: MouseEvent) {
      const target = e.target as Node;
      const isClickInsideWrapper = wrapperRef.current?.contains(target);
      const isClickInsidePortal = portalRef.current?.contains(target);

      if (!isClickInsideWrapper && !isClickInsidePortal) {
        setOpen(false);
        setSearch("");
      }
    }

    if (open) {
      document.addEventListener("mousedown", handleClickOutside);
      return () =>
        document.removeEventListener("mousedown", handleClickOutside);
    }
  }, [open]);

  const filteredCountries = useMemo(() => {
    const q = search.trim().toLowerCase().replace("+", "");
    if (!q) return defaultCountries;
    return defaultCountries.filter((c) => {
      const { name, dialCode, iso2 } = parseCountry(c);
      return (
        name.toLowerCase().includes(q) ||
        dialCode.includes(q) ||
        iso2.includes(q)
      );
    });
  }, [search]);

  function handleSelect(iso2: CountryIso2) {
    setCountry(iso2);
    setOpen(false);
    setSearch("");
    inputRef.current?.focus();
  }

  function handleKeyDown(e: React.KeyboardEvent) {
    if (e.key === "Escape") {
      setOpen(false);
      setSearch("");
    }
  }

  return (
    <div ref={wrapperRef} className="relative">
      {/* Unified bordered control: chip + input share ONE border, no gap */}
      <div
        className={`
          flex items-stretch overflow-hidden h-10 2xl:h-12 bg-white w-full rounded-md 2xl:rounded-xl border
          transition-color
          ${hasError ? "border-red-400" : "border-[#E5DFFF]"}
          font-body text-sm text-heading outline-none transition-all placeholder:text-gray-400 focus:border-[#8B5CF6] focus:ring-2 focus:ring-[#8B5CF6]/10
        `}
      >
        <button
          ref={buttonRef}
          type="button"
          role="combobox"
          aria-haspopup="listbox"
          aria-expanded={open}
          onClick={() => setOpen((o) => !o)}
          onKeyDown={handleKeyDown}
          className="flex items-center gap-1.5 border-r border-gray-200 bg-gray-50 px-2.5 outline-none hover:bg-gray-100 cursor-pointer"
        >
          <FlagImage
            iso2={country.iso2}
            style={{ width: 20, height: 14, borderRadius: 2 }}
          />
          <span className="text-sm text-gray-700">+{country.dialCode}</span>
          <svg
            className={`h-3 w-3 text-gray-400 transition-transform ${
              open ? "rotate-180" : ""
            }`}
            fill="none"
            viewBox="0 0 24 24"
            stroke="currentColor"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M19 9l-7 7-7-7"
            />
          </svg>
        </button>

        <input
          ref={inputRef}
          value={inputValue}
          onChange={handlePhoneValueChange}
          type="tel"
          placeholder={placeholder}
          className="custom-phone-number-input flex-1 px-3 py-2  text-sm 2xl:text-base outline-none w-full"
        />
      </div>

      {/* Dropdown using Portal for auto-positioning */}
      {open &&
        dropdownPosition &&
        createPortal(
          <div
            ref={portalRef}
            role="listbox"
            className="fixed z-999 overflow-hidden rounded-lg border border-gray-200 bg-white shadow-xl animate-in fade-in duration-100"
            style={{
              top: `${dropdownPosition.top}px`,
              left: `${dropdownPosition.left}px`,
              width: `${dropdownPosition.width}px`,
              minWidth: "260px",
            }}
          >
            <div className="border-b border-gray-100 p-2">
              <input
                ref={searchInputRef}
                value={search}
                onChange={(e) => setSearch(e.target.value)}
                onKeyDown={handleKeyDown}
                placeholder="Search country or dial code"
                className="w-full rounded-md p-2 border border-[#E5DFFF] 
                        font-body  text-sm 2xl:text-base text-heading outline-none transition-all placeholder:text-gray-400 focus:border-[#8B5CF6] focus:ring-2 focus:ring-[#8B5CF6]/10"
              />
            </div>

            <ul className="max-h-60 overflow-y-auto py-1">
              {filteredCountries.length === 0 && (
                <li className="px-3 py-2 text-sm text-gray-400">
                  No countries found
                </li>
              )}
              {filteredCountries.map((c) => {
                const parsed = parseCountry(c);
                const isSelected = parsed.iso2 === country.iso2;
                return (
                  <li key={parsed.iso2}>
                    <button
                      type="button"
                      role="option"
                      aria-selected={isSelected}
                      onClick={() => handleSelect(parsed.iso2)}
                      className={`
                        flex w-full items-center gap-2.5 px-3 py-2 text-left text-sm hover:bg-gray-50 cursor-pointer
                        ${isSelected ? "bg-gray-50 font-medium" : ""}
                      `}
                    >
                      <FlagImage
                        iso2={parsed.iso2}
                        style={{ width: 18, height: 13, borderRadius: 2 }}
                      />
                      <span className="flex-1 truncate text-gray-700">
                        {parsed.name}
                      </span>
                      <span className="tabular-nums text-gray-400">
                        +{parsed.dialCode}
                      </span>
                    </button>
                  </li>
                );
              })}
            </ul>
          </div>,
          document.body,
        )}
    </div>
  );
}
