"use client";

/**
 * Settings → Profile
 * ──────────────────
 * Profile edit surface. Identity fields (first/last name, avatar,
 * primary email, password) live in Clerk — edits go through the
 * Clerk SDK and Clerk is the source of truth. meSEO-side fields
 * (timezone) persist to our DB via /api/me/profile.
 *
 * Layout:
 *   - Avatar with click-to-replace (Clerk setProfileImage)
 *   - Editable First / Last name inputs → user.update(...)
 *   - Read-only primary email + "Manage Emails" redirect to Clerk's
 *     full user profile (email changes require verification which is
 *     cleaner in Clerk's hosted modal)
 *   - Change Password button → Clerk's user profile /security
 *   - Timezone dropdown (IANA zones) → PATCH /api/me/profile
 *   - "Manage Account in Clerk" escape hatch to the full profile
 */

import { useEffect, useRef, useState } from "react";
import { useUser, useClerk } from "@clerk/nextjs";
import { User, ExternalLink, Camera, KeyRound, Loader2, Check, Clock } from "lucide-react";

// A small curated IANA zone list. Covers the business cases (every
// brand we ship to is US-heavy with scattered international teams)
// without dumping the full 400-entry IANA tree into a <select>.
// Intl.supportedValuesOf("timeZone") would be more complete but isn't
// universally supported and is noisy for the typical user.
const TIMEZONES: Array<{ value: string; label: string }> = [
  { value: "America/New_York",    label: "Eastern (New York)" },
  { value: "America/Chicago",     label: "Central (Chicago)" },
  { value: "America/Denver",      label: "Mountain (Denver)" },
  { value: "America/Phoenix",     label: "Arizona (Phoenix, no DST)" },
  { value: "America/Los_Angeles", label: "Pacific (Los Angeles)" },
  { value: "America/Anchorage",   label: "Alaska (Anchorage)" },
  { value: "Pacific/Honolulu",    label: "Hawaii (Honolulu)" },
  { value: "America/Toronto",     label: "Toronto" },
  { value: "America/Mexico_City", label: "Mexico City" },
  { value: "America/Sao_Paulo",   label: "São Paulo" },
  { value: "Europe/London",       label: "London" },
  { value: "Europe/Dublin",       label: "Dublin" },
  { value: "Europe/Paris",        label: "Paris / Berlin / Madrid" },
  { value: "Europe/Amsterdam",    label: "Amsterdam" },
  { value: "Europe/Stockholm",    label: "Stockholm" },
  { value: "Europe/Warsaw",       label: "Warsaw" },
  { value: "Europe/Istanbul",     label: "Istanbul" },
  { value: "Africa/Johannesburg", label: "Johannesburg" },
  { value: "Asia/Dubai",          label: "Dubai" },
  { value: "Asia/Karachi",        label: "Karachi" },
  { value: "Asia/Kolkata",        label: "Mumbai / Kolkata" },
  { value: "Asia/Bangkok",        label: "Bangkok" },
  { value: "Asia/Singapore",      label: "Singapore" },
  { value: "Asia/Hong_Kong",      label: "Hong Kong" },
  { value: "Asia/Tokyo",          label: "Tokyo" },
  { value: "Asia/Seoul",          label: "Seoul" },
  { value: "Australia/Sydney",    label: "Sydney" },
  { value: "Australia/Perth",     label: "Perth" },
  { value: "Pacific/Auckland",    label: "Auckland" },
  { value: "UTC",                 label: "UTC" },
];

/** Best-effort detection of the browser's IANA zone. Falls back to
 *  UTC so the dropdown always has a valid default. */
function detectTimezone(): string {
  try {
    return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
  } catch { return "UTC"; }
}

export default function ProfileTab() {
  const { user, isLoaded } = useUser();
  const { openUserProfile } = useClerk();

  const [firstName, setFirstName] = useState("");
  const [lastName, setLastName] = useState("");
  const [timezone, setTimezone] = useState<string>("");
  const [dbLoaded, setDbLoaded] = useState(false);
  const [saving, setSaving] = useState(false);
  const [toast, setToast] = useState<string | null>(null);
  const fileRef = useRef<HTMLInputElement | null>(null);
  const [uploading, setUploading] = useState(false);

  const show = (msg: string) => { setToast(msg); setTimeout(() => setToast(null), 1800); };

  // Seed form state from Clerk once the user resolves.
  useEffect(() => {
    if (!isLoaded || !user) return;
    setFirstName(user.firstName || "");
    setLastName(user.lastName || "");
  }, [isLoaded, user]);

  // Load the DB-side fields (timezone) separately.
  useEffect(() => {
    let cancelled = false;
    fetch("/api/me/profile")
      .then((r) => (r.ok ? r.json() : null))
      .then((data) => {
        if (cancelled || !data) return;
        setTimezone(data.timezone || detectTimezone());
        setDbLoaded(true);
      })
      .catch(() => { if (!cancelled) { setTimezone(detectTimezone()); setDbLoaded(true); } });
    return () => { cancelled = true; };
  }, []);

  async function saveName() {
    if (!user) return;
    setSaving(true);
    try {
      await user.update({ firstName, lastName });
      show("Name updated");
    } catch (err) {
      show(err instanceof Error ? err.message : "Save failed");
    } finally {
      setSaving(false);
    }
  }

  async function saveTimezone(next: string) {
    setTimezone(next);
    try {
      const res = await fetch("/api/me/profile", {
        method: "PATCH",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ timezone: next }),
      });
      if (res.ok) show("Timezone saved");
      else show("Save failed");
    } catch { show("Save failed"); }
  }

  async function onAvatarChange(e: React.ChangeEvent<HTMLInputElement>) {
    const file = e.target.files?.[0];
    if (!file || !user) return;
    // Basic client-side guard — Clerk also rejects non-images, but a
    // preflight here avoids a bounced upload on the common misclick.
    if (!file.type.startsWith("image/")) { show("Pick an image file"); return; }
    if (file.size > 5 * 1024 * 1024) { show("Max 5MB"); return; }
    setUploading(true);
    try {
      await user.setProfileImage({ file });
      show("Avatar updated");
    } catch (err) {
      show(err instanceof Error ? err.message : "Upload failed");
    } finally {
      setUploading(false);
      if (fileRef.current) fileRef.current.value = "";
    }
  }

  if (!isLoaded) {
    return <div className="flex items-center justify-center py-16"><Loader2 className="w-5 h-5 text-slate-400 animate-spin" /></div>;
  }

  const primaryEmail = user?.primaryEmailAddress?.emailAddress ?? "";
  const nameDirty = (user?.firstName ?? "") !== firstName || (user?.lastName ?? "") !== lastName;

  return (
    <div className="space-y-6">
      <div className="bg-white rounded-xl border border-slate-200 overflow-hidden">
        <div className="px-6 py-4 border-b border-slate-100 flex items-center gap-2">
          <User className="w-4 h-4 text-brand-600" />
          <h2 className="font-bold text-slate-800 text-sm">Profile</h2>
        </div>
        <div className="px-6 py-5">
          {/* Avatar */}
          <div className="flex items-center gap-4 mb-6">
            <div className="relative w-16 h-16 shrink-0">
              {user?.imageUrl ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img src={user.imageUrl} alt="" className="w-16 h-16 rounded-xl object-cover" />
              ) : (
                <div className="w-16 h-16 rounded-xl bg-brand-100 flex items-center justify-center text-brand-600 font-bold text-xl">
                  {(user?.firstName?.[0] ?? primaryEmail[0] ?? "?").toUpperCase()}
                </div>
              )}
              <button
                type="button"
                onClick={() => fileRef.current?.click()}
                disabled={uploading}
                title="Replace avatar"
                className="absolute -bottom-1 -right-1 w-6 h-6 rounded-full bg-slate-900 text-white flex items-center justify-center shadow-md hover:bg-slate-800 disabled:opacity-60"
              >
                {uploading ? <Loader2 className="w-3 h-3 animate-spin" /> : <Camera className="w-3 h-3" />}
              </button>
              <input
                ref={fileRef}
                type="file"
                accept="image/*"
                onChange={onAvatarChange}
                className="hidden"
              />
            </div>
            <div className="min-w-0">
              <p className="text-lg font-bold text-slate-900 truncate">
                {user?.fullName?.trim() || "—"}
              </p>
              <p className="text-sm text-slate-500 truncate">{primaryEmail}</p>
            </div>
          </div>

          {/* Name editors */}
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 mb-3">
            <div>
              <label className="block text-[11px] font-semibold text-slate-600 mb-1">First Name</label>
              <input
                type="text"
                value={firstName}
                onChange={(e) => setFirstName(e.target.value)}
                className="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500/40"
              />
            </div>
            <div>
              <label className="block text-[11px] font-semibold text-slate-600 mb-1">Last Name</label>
              <input
                type="text"
                value={lastName}
                onChange={(e) => setLastName(e.target.value)}
                className="w-full px-3 py-2 text-sm border border-slate-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500/40"
              />
            </div>
          </div>
          <div className="flex items-center gap-2 mb-6">
            <button
              onClick={saveName}
              disabled={!nameDirty || saving}
              className="inline-flex items-center gap-1.5 px-4 py-2 bg-brand-600 text-white text-xs font-semibold rounded-lg hover:bg-brand-700 disabled:opacity-50"
            >
              {saving ? <Loader2 className="w-3.5 h-3.5 animate-spin" /> : <Check className="w-3.5 h-3.5" />}
              {saving ? "Saving…" : "Save name"}
            </button>
            {!nameDirty && <span className="text-[11px] text-slate-400">No changes</span>}
          </div>

          {/* Email (read-only — changes flow through Clerk's hosted
              profile so verification + primary selection stay in the
              supported path) */}
          <div className="mb-6">
            <label className="block text-[11px] font-semibold text-slate-600 mb-1">Primary Email</label>
            <div className="flex items-center gap-2">
              <input
                type="text"
                readOnly
                value={primaryEmail}
                className="flex-1 px-3 py-2 text-sm border border-slate-200 rounded-lg bg-slate-50"
              />
              <button
                onClick={() => openUserProfile()}
                className="px-3 py-2 border border-slate-200 rounded-lg text-xs font-semibold text-slate-700 hover:bg-slate-50"
              >
                Manage Emails
              </button>
            </div>
            <p className="text-[11px] text-slate-400 mt-1">
              Adding or changing emails happens in Clerk&apos;s account modal so the verification flow stays intact.
            </p>
          </div>

          {/* Timezone */}
          <div className="mb-6">
            <label className="block text-[11px] font-semibold text-slate-600 mb-1 flex items-center gap-1.5">
              <Clock className="w-3 h-3" /> Timezone
            </label>
            <select
              value={timezone}
              onChange={(e) => saveTimezone(e.target.value)}
              disabled={!dbLoaded}
              className="w-full max-w-md px-3 py-2 text-sm border border-slate-200 rounded-lg bg-white disabled:opacity-50"
            >
              {/* If the saved zone isn't in our curated list, include
                  it as a synthetic first option so the user's actual
                  setting isn't silently reset on save. */}
              {timezone && !TIMEZONES.some((t) => t.value === timezone) && (
                <option value={timezone}>{timezone} (current)</option>
              )}
              {TIMEZONES.map((t) => (
                <option key={t.value} value={t.value}>{t.label}</option>
              ))}
            </select>
            <p className="text-[11px] text-slate-400 mt-1">
              Used by scheduled email reports and cron runs so deliveries fire at your local hour, not UTC.
            </p>
          </div>

          {/* Account action row */}
          <div className="flex flex-wrap items-center gap-2 pt-4 border-t border-slate-100">
            <button
              onClick={() => openUserProfile()}
              className="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg border border-slate-200 text-xs font-semibold text-slate-700 hover:bg-slate-50"
            >
              <ExternalLink className="w-3.5 h-3.5" /> Manage Account in Clerk
            </button>
            <button
              onClick={() => openUserProfile({ __experimental_startPath: "/security" } as unknown as Parameters<typeof openUserProfile>[0])}
              className="inline-flex items-center gap-1.5 px-4 py-2 rounded-lg border border-slate-200 text-xs font-semibold text-slate-700 hover:bg-slate-50"
            >
              <KeyRound className="w-3.5 h-3.5" /> Change Password
            </button>
          </div>
        </div>
      </div>

      {toast && (
        <div className="fixed top-4 right-4 z-50 px-4 py-2 rounded-lg bg-slate-900 text-white text-xs font-semibold shadow-lg">
          {toast}
        </div>
      )}
    </div>
  );
}
