'use client';

import { useState, useEffect, useRef, useCallback } from 'react';
import { User, Mail, Phone, MapPin, Calendar, Shield, Camera, Check, X, AlertCircle, CheckCircle2, KeyRound } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Skeleton } from '@/components/ui/skeleton';
import { StatCard } from '@/components/ui/stat-card';
import { Input } from '@/components/ui/input';
import { useAuthStore } from '@/store/auth.store';
import { authService } from '@/services/auth.service';
import { getErrorMessage } from '@/lib/errors';
import { cn, colorFromString, getDisplayName } from '@/lib/utils';
import { useSystemConfig } from '@/hooks/useSystemConfig';
import ChangePasswordDialog from '@/components/auth/ChangePasswordDialog';

type CountryCode = { code: string; label: string; flag: string };

const COUNTRY_CODES: CountryCode[] = [
  { code: '+1', label: 'US', flag: '🇺🇸' },
  { code: '+44', label: 'GB', flag: '🇬🇧' },
  { code: '+91', label: 'IN', flag: '🇮🇳' },
  { code: '+971', label: 'AE', flag: '🇦🇪' },
  { code: '+966', label: 'SA', flag: '🇸🇦' },
  { code: '+61', label: 'AU', flag: '🇦🇺' },
  { code: '+49', label: 'DE', flag: '🇩🇪' },
  { code: '+33', label: 'FR', flag: '🇫🇷' },
  { code: '+81', label: 'JP', flag: '🇯🇵' },
  { code: '+86', label: 'CN', flag: '🇨🇳' },
  { code: '+82', label: 'KR', flag: '🇰🇷' },
  { code: '+55', label: 'BR', flag: '🇧🇷' },
  { code: '+7', label: 'RU', flag: '🇷🇺' },
  { code: '+52', label: 'MX', flag: '🇲🇽' },
  { code: '+234', label: 'NG', flag: '🇳🇬' },
  { code: '+27', label: 'ZA', flag: '🇿🇦' },
  { code: '+65', label: 'SG', flag: '🇸🇬' },
  { code: '+60', label: 'MY', flag: '🇲🇾' },
  { code: '+63', label: 'PH', flag: '🇵🇭' },
  { code: '+84', label: 'VN', flag: '🇻🇳' },
];

type AlertType = 'success' | 'error';

interface FormData {
  firstName: string;
  lastName: string;
  email: string;
  phone: string;
  countryCode: string;
  dateOfBirth: string;
  country: string;
  city: string;
  address: string;
}

export default function UserProfilePage() {
  const sysConfig = useSystemConfig();
  const user = useAuthStore((s) => s.user);
  const setUser = useAuthStore((s) => s.setUser);

  const [loading, setLoading] = useState(true);
  const [saving, setSaving] = useState(false);
  const [alert, setAlert] = useState<{ type: AlertType; message: string } | null>(null);
  const [avatarPreview, setAvatarPreview] = useState<string | null>(null);
  const [avatarFile, setAvatarFile] = useState<File | null>(null);
  const [showCountryCodes, setShowCountryCodes] = useState(false);
  const [showChangePassword, setShowChangePassword] = useState(false);
  const [passwordChanged, setPasswordChanged] = useState(false);
  const fileInputRef = useRef<HTMLInputElement>(null);
  const countryCodeRef = useRef<HTMLDivElement>(null);

  const [formData, setFormData] = useState<FormData>({
    firstName: '',
    lastName: '',
    email: '',
    phone: '',
    countryCode: '+1',
    dateOfBirth: '',
    country: '',
    city: '',
    address: '',
  });

  const fetchProfile = useCallback(async () => {
    try {
      const res = await authService.getProfile();
      const profile = res.data?.data?.user ?? res.data?.data ?? res.data?.user ?? res.data;
      if (profile) {
        // Split phone into country code + local number if it starts with + or digit
        const rawPhone: string = profile.phone ?? '';
        let detectedCode = '+1';
        let localPhone = rawPhone;
        for (const cc of COUNTRY_CODES) {
          if (rawPhone.startsWith(cc.code)) {
            detectedCode = cc.code;
            localPhone = rawPhone.slice(cc.code.length);
            break;
          }
        }
        setFormData({
          firstName: profile.firstName ?? '',
          lastName: profile.lastName ?? '',
          email: profile.email ?? '',
          phone: localPhone,
          countryCode: detectedCode,
          dateOfBirth: profile.dateOfBirth ? String(profile.dateOfBirth).slice(0, 10) : '',
          country: profile.country ?? '',
          city: profile.city ?? '',
          address: profile.address ?? '',
        });
        if (profile.profilePictureUrl) {
          setAvatarPreview(profile.profilePictureUrl);
        }
      }
    } catch (err) {
      setAlert({ type: 'error', message: getErrorMessage(err) });
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchProfile();
  }, [fetchProfile]);

  useEffect(() => {
    if (!alert) return;
    const t = setTimeout(() => setAlert(null), 5000);
    return () => clearTimeout(t);
  }, [alert]);

  useEffect(() => {
    function handleClickOutside(e: MouseEvent) {
      if (countryCodeRef.current && !countryCodeRef.current.contains(e.target as Node)) {
        setShowCountryCodes(false);
      }
    }
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  const updateField = (field: keyof FormData, value: string) => {
    setFormData((prev) => ({ ...prev, [field]: value }));
  };

  const handleAvatarChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    if (file.size > sysConfig.avatarMaxSizeMb * 1024 * 1024) {
      setAlert({ type: 'error', message: `Image must be under ${sysConfig.avatarMaxSizeMb}MB.` });
      return;
    }
    if (!file.type.startsWith('image/')) {
      setAlert({ type: 'error', message: 'Please select a valid image file.' });
      return;
    }
    setAvatarFile(file);
    const reader = new FileReader();
    reader.onload = () => setAvatarPreview(reader.result as string);
    reader.readAsDataURL(file);
  };

  const uploadAvatar = async (): Promise<string | undefined> => {
    if (!avatarFile) return formData.email ? avatarPreview ?? undefined : undefined;

    const formDataObj = new FormData();
    formDataObj.append('file', avatarFile);

    try {
      const res = await fetch('/api/upload', { method: 'POST', body: formDataObj });
      if (!res.ok) throw new Error('Upload failed');
      const result = await res.json();
      return result.url ?? result.data?.url;
    } catch {
      setAlert({ type: 'error', message: 'Failed to upload profile picture.' });
      return undefined;
    }
  };

  const handleSave = async () => {
    setAlert(null);
    setSaving(true);

    try {
      const profilePictureUrl = await uploadAvatar();

      const payload: Record<string, unknown> = {
        firstName: formData.firstName,
        lastName: formData.lastName,
        phone: formData.phone ? `${formData.countryCode}${formData.phone.replace(/\D/g, '')}` : '',
        dateOfBirth: formData.dateOfBirth || undefined,
        country: formData.country || undefined,
        city: formData.city || undefined,
        address: formData.address || undefined,
      };

      if (profilePictureUrl) {
        payload.profilePictureUrl = profilePictureUrl;
      }

      const res = await authService.updateProfile(payload);
      const updatedUser = res.data?.data ?? res.data;

      if (updatedUser) {
        setUser({
          id: updatedUser.id ?? user?.id ?? '',
          email: updatedUser.email ?? formData.email,
          firstName: updatedUser.firstName ?? formData.firstName,
          lastName: updatedUser.lastName ?? formData.lastName,
          phone: updatedUser.phone ?? formData.phone,
          role: user?.role ?? 'USER',
          isEmailVerified: updatedUser.isEmailVerified ?? user?.isEmailVerified ?? false,
          isTwoFactorEnabled: updatedUser.isTwoFactorEnabled ?? user?.isTwoFactorEnabled ?? false,
          profilePictureUrl: updatedUser.profilePictureUrl ?? profilePictureUrl,
          createdAt: updatedUser.createdAt,
        });

        if (updatedUser.firstName) {
          setFormData((prev) => ({ ...prev, firstName: updatedUser.firstName, lastName: updatedUser.lastName ?? prev.lastName }));
        }
      }

      setAlert({ type: 'success', message: 'Profile updated successfully.' });
    } catch (err) {
      setAlert({ type: 'error', message: getErrorMessage(err) });
    } finally {
      setSaving(false);
    }
  };

  const displayName = getDisplayName({
    firstName: formData.firstName,
    lastName: formData.lastName,
    email: formData.email,
  });
  const avatarLetter = displayName.charAt(0).toUpperCase();
  const avatarColor = colorFromString(formData.email || displayName);

  const isLoading = loading;

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold tracking-tight text-ink">Profile</h1>
        <p className="mt-1 text-sm text-ink-muted">Manage your personal information</p>
      </div>

      {/* Stats */}
      <div className="grid grid-cols-1 gap-4 sm:grid-cols-3">
        {isLoading ? (
          Array.from({ length: 3 }).map((_, i) => (
            <div key={i} className="card p-5">
              <Skeleton className="h-4 w-24" />
              <Skeleton className="mt-3 h-8 w-20" />
            </div>
          ))
        ) : (
          <>
            <StatCard label="Member Since" value={user?.createdAt ? new Date(user.createdAt).getFullYear() : '—'} icon={Calendar} iconClass="bg-primary-100 text-primary-600 dark:bg-primary-500/15 dark:text-primary-300" />
            <StatCard label="Email Status" value={user?.isEmailVerified ? 'Verified' : 'Unverified'} icon={Mail} iconClass="bg-emerald-100 text-emerald-600 dark:bg-emerald-500/15 dark:text-emerald-300" />
            <StatCard label="2FA Status" value={user?.isTwoFactorEnabled ? 'Enabled' : 'Disabled'} icon={Shield} iconClass="bg-amber-100 text-amber-600 dark:bg-amber-500/15 dark:text-amber-300" />
          </>
        )}
      </div>

      <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
        {/* Avatar card */}
        <Card>
          <CardHeader>
            <CardTitle>Profile Photo</CardTitle>
            <CardDescription>Upload a new avatar</CardDescription>
          </CardHeader>
          <CardContent className="flex flex-col items-center text-center">
            {isLoading ? (
              <>
                <Skeleton className="h-24 w-24 rounded-full" />
                <Skeleton className="mt-4 h-5 w-24" />
                <Skeleton className="mt-2 h-4 w-32" />
              </>
            ) : (
              <>
                <div className="relative">
                  {avatarPreview ? (
                    <img
                      src={avatarPreview}
                      alt="Profile"
                      className="h-24 w-24 rounded-full object-cover ring-2 ring-border"
                    />
                  ) : (
                    <div
                      className="flex h-24 w-24 items-center justify-center rounded-full text-3xl font-bold text-white"
                      style={{ backgroundColor: avatarColor }}
                    >
                      {avatarLetter}
                    </div>
                  )}
                  <label
                    htmlFor="avatar-upload"
                    className="absolute -bottom-1 -right-1 flex h-8 w-8 cursor-pointer items-center justify-center rounded-full bg-surface-raised text-ink-muted hover:text-ink border border-line transition-colors"
                  >
                    <Camera className="h-4 w-4" />
                    <input
                      ref={fileInputRef}
                      id="avatar-upload"
                      type="file"
                      className="hidden"
                      accept="image/*"
                      onChange={handleAvatarChange}
                    />
                  </label>
                </div>
                <h3 className="mt-4 text-lg font-semibold text-ink">{displayName}</h3>
                <p className="text-sm text-ink-muted">{formData.email}</p>
                <div className="mt-3 flex items-center gap-1.5">
                  {user?.isEmailVerified ? (
                    <Badge variant="success" className="gap-1">
                      <CheckCircle2 className="h-3.5 w-3.5" />
                      Verified
                    </Badge>
                  ) : (
                    <Badge variant="warning" className="gap-1">
                      <AlertCircle className="h-3.5 w-3.5" />
                      Unverified
                    </Badge>
                  )}
                </div>
                <p className="mt-3 text-xs text-ink-faint">
                  JPG, PNG or GIF. Max {sysConfig.avatarMaxSizeMb}MB.
                </p>
              </>
            )}
          </CardContent>
        </Card>

        {/* Personal info form */}
        <Card className="lg:col-span-2">
          <CardHeader>
            <CardTitle>Personal Information</CardTitle>
            <CardDescription className="mt-1">Update your personal details</CardDescription>
          </CardHeader>
          <CardContent>
            {alert && (
              <div
                className={cn(
                  'mb-5 flex items-center gap-2.5 rounded-xl border px-4 py-3 text-sm',
                  alert.type === 'success'
                    ? 'border-emerald-500/30 bg-emerald-500/10 text-emerald-600 dark:text-emerald-400'
                    : 'border-red-500/30 bg-red-500/10 text-red-600 dark:text-red-400',
                )}
              >
                {alert.type === 'success' ? (
                  <CheckCircle2 className="h-4 w-4 shrink-0" />
                ) : (
                  <AlertCircle className="h-4 w-4 shrink-0" />
                )}
                <span className="flex-1">{alert.message}</span>
                <button
                  type="button"
                  onClick={() => setAlert(null)}
                  className="shrink-0 rounded-lg p-0.5 opacity-70 hover:opacity-100"
                >
                  <X className="h-3.5 w-3.5" />
                </button>
              </div>
            )}

            {isLoading ? (
              <div className="space-y-4">
                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                  {Array.from({ length: 6 }).map((_, i) => (
                    <div key={i} className="space-y-2">
                      <Skeleton className="h-4 w-20" />
                      <Skeleton className="h-10 w-full" />
                    </div>
                  ))}
                </div>
                <Skeleton className="h-10 w-full sm:w-32" />
              </div>
            ) : (
              <>
                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                  <div className="space-y-1.5">
                    <label htmlFor="firstName" className="block text-sm font-medium text-ink">
                      First Name <span className="text-red-500">*</span>
                    </label>
                    <Input
                      id="firstName"
                      icon={<User className="h-4 w-4" />}
                      value={formData.firstName}
                      onChange={(e) => updateField('firstName', e.target.value)}
                      placeholder="Enter first name"
                      required
                    />
                  </div>

                  <div className="space-y-1.5">
                    <label htmlFor="lastName" className="block text-sm font-medium text-ink">
                      Last Name <span className="text-red-500">*</span>
                    </label>
                    <Input
                      id="lastName"
                      icon={<User className="h-4 w-4" />}
                      value={formData.lastName}
                      onChange={(e) => updateField('lastName', e.target.value)}
                      placeholder="Enter last name"
                      required
                    />
                  </div>

                  <div className="space-y-1.5">
                    <label htmlFor="email" className="block text-sm font-medium text-ink">
                      Email
                    </label>
                    <Input
                      id="email"
                      icon={<Mail className="h-4 w-4" />}
                      value={formData.email}
                      readOnly
                      disabled
                      className="bg-surface-raised text-ink-secondary cursor-not-allowed"
                    />
                  </div>

                  <div className="space-y-1.5">
                    <label htmlFor="phone" className="block text-sm font-medium text-ink">
                      Phone
                    </label>
                    <div className="flex gap-2">
                      <div className="relative" ref={countryCodeRef}>
                        <button
                          type="button"
                          onClick={() => setShowCountryCodes((v) => !v)}
                          className="flex items-center gap-1 rounded-xl border border-line bg-surface px-2.5 py-2 text-sm text-ink hover:bg-surface-raised transition-colors min-w-[80px] justify-between"
                        >
                          <span>{formData.countryCode}</span>
                          <svg className="h-3.5 w-3.5 text-ink-faint" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                          </svg>
                        </button>
                        {showCountryCodes && (
                          <div className="absolute z-50 mt-1 max-h-48 w-40 overflow-y-auto rounded-xl border border-line bg-surface shadow-lg">
                            {COUNTRY_CODES.map((cc) => (
                              <button
                                key={cc.code}
                                type="button"
                                onClick={() => {
                                  updateField('countryCode', cc.code);
                                  setShowCountryCodes(false);
                                }}
                                className={cn(
                                  'flex w-full items-center gap-2 px-3 py-2 text-left text-sm hover:bg-surface-raised transition-colors',
                                  formData.countryCode === cc.code && 'bg-primary-500/10 text-primary-600',
                                )}
                              >
                                <span>{cc.flag}</span>
                                <span className="flex-1">{cc.code}</span>
                                <span className="text-xs text-ink-faint">{cc.label}</span>
                              </button>
                            ))}
                          </div>
                        )}
                      </div>
                      <div className="flex-1">
                        <Input
                          id="phone"
                          icon={<Phone className="h-4 w-4" />}
                          value={formData.phone}
                          onChange={(e) => updateField('phone', e.target.value)}
                          placeholder="555 123 4567"
                          type="tel"
                        />
                      </div>
                    </div>
                  </div>

                  <div className="space-y-1.5">
                    <label htmlFor="dateOfBirth" className="block text-sm font-medium text-ink">
                      Date of Birth
                    </label>
                    <Input
                      id="dateOfBirth"
                      icon={<Calendar className="h-4 w-4" />}
                      type="date"
                      value={formData.dateOfBirth}
                      onChange={(e) => updateField('dateOfBirth', e.target.value)}
                    />
                  </div>

                  <div className="space-y-1.5">
                    <label htmlFor="country" className="block text-sm font-medium text-ink">
                      Country
                    </label>
                    <Input
                      id="country"
                      icon={<MapPin className="h-4 w-4" />}
                      value={formData.country}
                      onChange={(e) => updateField('country', e.target.value)}
                      placeholder="Enter country"
                    />
                  </div>

                  <div className="space-y-1.5">
                    <label htmlFor="city" className="block text-sm font-medium text-ink">
                      City
                    </label>
                    <Input
                      id="city"
                      icon={<MapPin className="h-4 w-4" />}
                      value={formData.city}
                      onChange={(e) => updateField('city', e.target.value)}
                      placeholder="Enter city"
                    />
                  </div>

                  <div className="space-y-1.5 sm:col-span-2">
                    <label htmlFor="address" className="block text-sm font-medium text-ink">
                      Address
                    </label>
                    <Input
                      id="address"
                      icon={<MapPin className="h-4 w-4" />}
                      value={formData.address}
                      onChange={(e) => updateField('address', e.target.value)}
                      placeholder="Enter your address"
                    />
                  </div>
                </div>

                <div className="flex flex-col-reverse items-center justify-end gap-3 pt-4 sm:flex-row">
                  {alert?.type === 'success' && (
                    <span className="flex items-center gap-1.5 text-sm font-medium text-emerald-600 dark:text-emerald-400">
                      <Check className="h-4 w-4" />
                      Saved
                    </span>
                  )}
                  <Button
                    variant="outline"
                    onClick={() => fetchProfile()}
                    disabled={saving}
                  >
                    Cancel
                  </Button>
                  <Button onClick={handleSave} isLoading={saving}>
                    {saving ? 'Saving...' : 'Save Changes'}
                  </Button>
                </div>
              </>
            )}
          </CardContent>
        </Card>
      </div>

      {/* Security / Change Password */}
      <Card>
        <CardHeader>
          <CardTitle className="flex items-center gap-2">
            <Shield className="h-4 w-4" /> Security
          </CardTitle>
          <CardDescription className="mt-1">Update the password used to sign in to your account</CardDescription>
        </CardHeader>
        <CardContent>
          <div className="flex flex-col items-start justify-between gap-4 rounded-xl border border-line bg-surface-raised p-4 sm:flex-row sm:items-center">
            <div className="flex items-start gap-3">
              <div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary-100 text-primary-600 dark:bg-primary-500/15 dark:text-primary-300">
                <KeyRound className="h-5 w-5" />
              </div>
              <div>
                <p className="text-sm font-medium text-ink">Change Password</p>
                <p className="mt-1 text-xs text-ink-muted">
                  Choose a strong password you have not used before. You will stay signed in on this device.
                </p>
                {passwordChanged && (
                  <p className="mt-2 flex items-center gap-1 text-xs font-medium text-emerald-600 dark:text-emerald-400">
                    <CheckCircle2 className="h-3.5 w-3.5" /> Password updated successfully.
                  </p>
                )}
              </div>
            </div>
            <Button
              variant="outline"
              onClick={() => {
                setPasswordChanged(false);
                setShowChangePassword(true);
              }}
            >
              <KeyRound className="h-4 w-4" /> Change Password
            </Button>
          </div>
        </CardContent>
      </Card>

      <ChangePasswordDialog
        open={showChangePassword}
        onClose={() => setShowChangePassword(false)}
        onSuccess={() => {
          setPasswordChanged(true);
          setTimeout(() => setPasswordChanged(false), 4000);
        }}
        title="Change Your Password"
        requireCurrentPassword
        variant="user"
      />
    </div>
  );
}
