import * as React from "react";
import { ChevronsUpDown, CheckCircle2, AlertCircle, Info } from "lucide-react";
import { useImperativeHandle } from "react";
import * as RPNInput from "react-phone-number-input";
import { parsePhoneNumber, validatePhoneNumberLength } from "libphonenumber-js";
import flags from "react-phone-number-input/flags";
import ar from "react-phone-number-input/locale/ar.json";

import { GhostButton } from "@/components/ui/settings-ui";
import {
    Command,
    CommandEmpty,
    CommandGroup,
    CommandInput,
    CommandItem,
    CommandList,
} from "@/components/ui/command";
import { Input } from "@/components/ui/input";
import {
    Popover,
    PopoverContent,
    PopoverTrigger,
} from "@/components/ui/popover";
import { ScrollArea } from "@/components/ui/scroll-area";
import { cn } from "@/lib/utils";


type PhoneInputProps = Omit<
    React.ComponentProps<"input">,
    "onChange" | "value" | "ref"
> &
    Omit<RPNInput.Props<typeof RPNInput.default>, "onChange"> & {
        onChange?: (value: RPNInput.Value) => void;
        inputClassName?: string;
        buttonClassName?: string;
        isAr?: boolean;
        hideMessage?: boolean;
        onValidationChange?: (status: { text: string, type: 'valid' | 'invalid' | 'waiting' | 'none', waStatus: 'found' | 'not' | 'none' }) => void;
    };

export interface PhoneInputRef {
    getNumber: () => string;
    clear: () => void;
}

const PhoneInput = React.forwardRef<PhoneInputRef, PhoneInputProps>(
    ({ className, onChange, value: propValue, onValidationChange, hideMessage, inputClassName, buttonClassName, isAr, defaultCountry, ...props }, ref) => {
            const [localValue, setLocalValue] = React.useState<string>("");
            const normalizedValue = React.useMemo(() => {
                const v = propValue !== undefined ? propValue : localValue;
                if (v && typeof v === "string" && /^\d+$/.test(v)) {
                    return `+${v}`;
                }
                return v;
            }, [propValue, localValue]);

            const value = normalizedValue;
            
            const handleValueChange = (val: string) => {
                if (propValue === undefined) {
                    setLocalValue(val);
                }
                onChange?.(val as RPNInput.Value);
            };

            useImperativeHandle(ref, () => ({
                getNumber: () => (value as string) || "",
                clear: () => handleValueChange("")
            }));
            const globalCountry = window.wawpDashboardData?.global?.country as RPNInput.Country | undefined;
            const initialCountry = defaultCountry || globalCountry;
            const [detectedCountry, setDetectedCountry] = React.useState<RPNInput.Country | undefined>(initialCountry);

            // Sync with global country changes
            const [prevGlobalCountry, setPrevGlobalCountry] = React.useState(globalCountry);
            if (globalCountry !== prevGlobalCountry) {
                setPrevGlobalCountry(globalCountry);
                if (!defaultCountry) {
                    setDetectedCountry(globalCountry);
                }
            }

            const actualIsAr = isAr ?? (typeof document !== 'undefined' && document.dir === 'rtl');
            const [validation, setValidation] = React.useState<{ status: 'valid' | 'invalid' | 'typing' | 'idle', message: string }>({ status: 'idle', message: '' });

            React.useEffect(() => {
                if (onValidationChange) {
                    const typeMap: Record<string, 'valid' | 'invalid' | 'waiting' | 'none'> = {
                        valid: 'valid',
                        invalid: 'invalid',
                        typing: 'waiting',
                        idle: 'none'
                    };
                    onValidationChange({
                        text: validation.message,
                        type: typeMap[validation.status] || 'none',
                        waStatus: 'none'
                    });
                }
            }, [validation, onValidationChange]);

            // Adjust state during render if value changes
            const [prevValue, setPrevValue] = React.useState(value);
            if (value !== prevValue) {
                setPrevValue(value);
                if (value && typeof value === 'string') {
                    const cleanValue = value.startsWith('+') ? value : '+' + value;
                    try {
                        const parsed = parsePhoneNumber(cleanValue);
                        if (parsed && parsed.country) {
                            setDetectedCountry(parsed.country);
                        }
                    } catch { /* ignored */ }
                }
            }

            // Adjust validation during render if value or actualIsAr changes
            const [prevValForValidation, setPrevValForValidation] = React.useState(value);
            const [prevIsArForValidation, setPrevIsArForValidation] = React.useState(actualIsAr);
            
            if (value !== prevValForValidation || actualIsAr !== prevIsArForValidation) {
                setPrevValForValidation(value);
                setPrevIsArForValidation(actualIsAr);
                
                if (!value || (value as string).length < 2) {
                    setValidation({ status: 'idle', message: '' });
                } else {
                    const str = value as string;
                    // Check for repeated country code (e.g. +2020...)
                    const matches = str.match(/^\+(\d+)(\1)/);
                    if (matches) {
                        setValidation({ 
                            status: 'invalid', 
                            message: actualIsAr ? 'كود الدولة متكرر مرتين' : 'Country code repeated twice' 
                        });
                    } else {
                        try {
                            const parsed = parsePhoneNumber(str);
                            if (parsed && parsed.isValid()) {
                                const type = parsed.getType ? parsed.getType() : null;
                                let typeStr = "";
                                if (type === 'MOBILE') typeStr = actualIsAr ? 'جوال' : 'Mobile';
                                else if (type === 'FIXED_LINE') typeStr = actualIsAr ? 'ثابت' : 'Fixed';
                                else if (type === 'FIXED_LINE_OR_MOBILE') typeStr = actualIsAr ? 'جوال/ثابت' : 'Mobile/Fixed';
                                else if (type === 'VOIP') typeStr = 'VoIP';
                                
                                const msg = typeStr 
                                    ? (actualIsAr ? `الرقم صحيح (${typeStr})` : `Valid ${typeStr}`)
                                    : (actualIsAr ? 'الرقم صحيح' : 'Number is valid');
                                
                                setValidation({ status: 'valid', message: msg });
                            } else {
                                const lengthStatus = validatePhoneNumberLength(str);
                                if (lengthStatus === 'TOO_SHORT') {
                                    setValidation({ status: 'typing', message: actualIsAr ? 'الرقم ناقص' : 'Number is too short' });
                                } else if (lengthStatus === 'TOO_LONG') {
                                    setValidation({ status: 'invalid', message: actualIsAr ? 'الرقم طويل جداً' : 'Number is too long' });
                                } else if (lengthStatus === 'INVALID_COUNTRY') {
                                    setValidation({ status: 'invalid', message: actualIsAr ? 'كود الدولة غير صحيح' : 'Invalid country code' });
                                } else {
                                     setValidation({ status: 'typing', message: actualIsAr ? 'رقم غير مكتمل' : 'Incomplete number' });
                                }
                            }
                        } catch {
                            setValidation({ status: 'typing', message: actualIsAr ? 'جاري التحقق...' : 'Validating...' });
                        }
                    }
                }
            }
            
            React.useEffect(() => {
                if (onValidationChange) {
                    onValidationChange({
                        text: validation.message || "",
                        type: validation.status === 'idle' ? 'none' : 
                              validation.status === 'typing' ? 'waiting' : 
                              (validation.status as 'valid' | 'invalid'),
                        waStatus: 'none' // Handled by parent if needed
                    });
                }
            }, [validation, onValidationChange]);

            const getSuffix = () => {
                if (validation.status === 'valid') return <CheckCircle2 className="w-4 h-4 text-emerald-500 animate-in zoom-in duration-300" />;
                if (validation.status === 'invalid') return <AlertCircle className="w-4 h-4 text-destructive animate-in shake-in duration-300" />;
                if (validation.status === 'typing') return <Info className="w-4 h-4 text-amber-500 animate-pulse" />;
                return null;
            };

            return (
                <div className="flex flex-col gap-1.5 w-full">
                    <div className={cn(
                        "group relative flex items-stretch border border-input bg-transparent rounded-lg transition-all duration-300 focus-within:ring-2 focus-within:ring-ring/20 focus-within:border-ring shadow-none",
                        className
                    )}>
                        <RPNInput.default
                            className="flex-1 flex items-stretch"
                            labels={actualIsAr ? ar : undefined}
                            countrySelectComponent={(selectProps) => (
                                <CountrySelect 
                                    {...selectProps} 
                                    isAr={actualIsAr} 
                                    buttonClassName={cn("z-10 h-full", buttonClassName)} 
                                />
                            )}
                            inputComponent={InputComponent}
                            {...({
                                isAr: actualIsAr,
                                inputClassName: cn(
                                    "!border-0 !border-none !shadow-none bg-transparent focus-visible:ring-0",
                                    inputClassName,
                                    actualIsAr ? "pl-10" : "pr-10"
                                )
                            } as Record<string, unknown>)}
                            smartCaret={false}
                            value={value || undefined}
                            onChange={(value) => handleValueChange(value || "")}
                            defaultCountry={detectedCountry}
                            {...props}
                        />
                        <div className={cn(
                            "absolute top-1/2 -translate-y-1/2 flex items-center justify-center pointer-events-none transition-all duration-300 z-20",
                            actualIsAr ? "left-3" : "right-3"
                        )}>
                            {getSuffix()}
                        </div>
                    </div>
                    {validation.message && !hideMessage && (
                        <p className={cn(
                            "text-[10px] font-bold px-1 uppercase tracking-tight transition-all duration-300 animate-in fade-in slide-in-from-top-1",
                            validation.status === 'valid' ? "text-emerald-500" : 
                            validation.status === 'invalid' ? "text-rose-500" : "text-amber-500"
                        )}>
                            {validation.message}
                        </p>
                    )}
                </div>
            );
        },
    );
PhoneInput.displayName = "PhoneInput";

const InputComponent = React.forwardRef<
    HTMLInputElement,
    React.ComponentProps<"input"> & { inputClassName?: string; isAr?: boolean }
>(({ className, inputClassName, isAr, ...props }, ref) => {
    const actualIsAr = isAr ?? (typeof document !== 'undefined' && document.dir === 'rtl');
    return (
        <div className="relative flex-1 h-full">
            <Input
                className={cn(
                    "!border-0 !border-none !shadow-none bg-transparent focus-visible:ring-0 h-full",
                    actualIsAr ? "pl-10" : "pr-10",
                    className,
                    inputClassName
                )}
                {...props}
                ref={ref}
            />
        </div>
    );
});
InputComponent.displayName = "InputComponent";

type CountryEntry = { label: string; value: RPNInput.Country | undefined };

type CountrySelectProps = {
    disabled?: boolean;
    value: RPNInput.Country;
    options: CountryEntry[];
    onChange: (country: RPNInput.Country) => void;
    buttonClassName?: string;
    isAr?: boolean;
};

const CountrySelect = ({
    disabled,
    value: selectedCountry,
    options: countryList,
    onChange,
    buttonClassName,
    isAr,
}: CountrySelectProps) => {
    const scrollAreaRef = React.useRef<HTMLDivElement>(null);
    const [searchValue, setSearchValue] = React.useState("");
    const [isOpen, setIsOpen] = React.useState(false);

    // If isAr is not passed (from RPNInput), detect from document
    const actualIsAr = isAr ?? (typeof document !== 'undefined' && document.dir === 'rtl');

    return (
        <Popover
            open={isOpen}
            modal
            onOpenChange={(open) => {
                setIsOpen(open);
                if (open) setSearchValue("");
            }}
        >
            <PopoverTrigger asChild>
                <GhostButton
                    type="button"
                    className={cn(
                        "flex gap-1.5 focus:z-10 cursor-pointer px-4 h-full border-r border-[#f1f5f9] rounded-none hover:bg-slate-50 transition-colors shadow-none",
                        actualIsAr && "border-r-0 border-l",
                        buttonClassName
                    )}
                    disabled={disabled}
                >
                    <FlagComponent
                        country={selectedCountry}
                        countryName={selectedCountry}
                    />
                    <ChevronsUpDown
                        className={cn(
                            "size-3.5 opacity-40 shrink-0",
                            disabled ? "hidden" : "opacity-40",
                        )}
                    />
                </GhostButton>
            </PopoverTrigger>
            <PopoverContent 
                className="w-[300px] p-0 z-50 rounded-xl" 
                align="start"
                sideOffset={8}
                dir={actualIsAr ? "rtl" : "ltr"}
            >
                <Command className="rounded-xl overflow-hidden shadow-2xl">
                    <CommandInput
                        value={searchValue}
                        onValueChange={(value) => {
                            setSearchValue(value);
                            setTimeout(() => {
                                if (scrollAreaRef.current) {
                                    const viewportElement = scrollAreaRef.current.querySelector(
                                        "[data-radix-scroll-area-viewport]",
                                    );
                                    if (viewportElement) {
                                        viewportElement.scrollTop = 0;
                                    }
                                }
                            }, 0);
                        }}
                        placeholder={actualIsAr ? "البحث عن دولة..." : "Search country..."}
                    />
                    <CommandList>
                        <ScrollArea ref={scrollAreaRef} className="h-72" dir={actualIsAr ? 'rtl' : 'ltr'}>
                            <CommandEmpty>{actualIsAr ? "لا توجد نتائج." : "No country found."}</CommandEmpty>
                            <CommandGroup>
                                {countryList.map(({ value, label }) => {
                                    // Manually translate if needed, though RPNInput should handle it via 'labels' prop
                                    let translatedLabel = actualIsAr && value && (ar as Record<string, string>)[value] 
                                        ? (ar as Record<string, string>)[value] 
                                        : label;

                                    // Custom override for IL
                                    if (value === 'IL') {
                                        translatedLabel = actualIsAr ? 'اراضي 48' : 'Territories of 48';
                                    }

                                    return value ? (
                                        <CountrySelectOption
                                            key={value}
                                            country={value}
                                            countryName={translatedLabel}
                                            selectedCountry={selectedCountry}
                                            onChange={onChange}
                                            onSelectComplete={() => setIsOpen(false)}
                                        />
                                    ) : null;
                                })}
                            </CommandGroup>
                        </ScrollArea>
                    </CommandList>
                </Command>
            </PopoverContent>
        </Popover>
    );
};

interface CountrySelectOptionProps extends RPNInput.FlagProps {
    selectedCountry: RPNInput.Country;
    onChange: (country: RPNInput.Country) => void;
    onSelectComplete: () => void;
}

const CountrySelectOption = ({
    country,
    countryName,
    selectedCountry,
    onChange,
    onSelectComplete,
}: CountrySelectOptionProps) => {
    const handleSelect = () => {
        onChange(country);
        onSelectComplete();
    };

    return (
        <CommandItem
            className="gap-2"
            onSelect={handleSelect}
            data-checked={country === selectedCountry}
        >
            <FlagComponent country={country} countryName={countryName} />
            <span className="flex-1 text-sm">{countryName}</span>
            <span className="text-sm text-foreground/50">{`+${RPNInput.getCountryCallingCode(country)}`}</span>
        </CommandItem>
    );
};

const FlagComponent = ({ country, countryName }: RPNInput.FlagProps) => {
    // Custom flag override: if IL, use PS flag
    const displayCountry = country === 'IL' ? 'PS' : country;
    const Flag = flags[displayCountry as keyof typeof flags];

    return (
        <span className="flex h-4 w-6 overflow-hidden rounded-xs bg-foreground/20 [&_svg:not([class*='size-'])]:size-full">
            {Flag && <Flag title={countryName} />}
        </span>
    );
};

export { PhoneInput };
export default PhoneInput;
