"use client";

import { AnimatePresence, motion } from "framer-motion";
import { Building2, Check, ChevronRight, LoaderCircle, MapPinned, Save, Sparkles, UserCircle2 } from "lucide-react";
import { useEffect, useMemo, useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { getIncompleteProfileFields } from "@/components/client-portal/shared";
import { formatDocument, getDocumentLabel, validateBrazilianDocument } from "@/lib/document-utils";
import { getReadableTextColor } from "@/lib/color-contrast";

type ClientProfile = {
  name?: string | null;
  company_name?: string | null;
  document?: string | null;
  email?: string | null;
  phone?: string | null;
  whatsapp?: string | null;
  address_zip?: string | null;
  address_street?: string | null;
  address_number?: string | null;
  address_complement?: string | null;
  address_neighborhood?: string | null;
  address_city?: string | null;
  address_state?: string | null;
  notes?: string | null;
};

export type OnboardingStep = 0 | 1;

export function PortalOnboardingStepper({
  step,
  primaryColor,
  onStepChange,
}: {
  step: OnboardingStep;
  primaryColor: string;
  onStepChange?: (step: OnboardingStep) => void;
}) {
  const stepItems = [
    { id: 0 as const, label: "Dados" },
    { id: 1 as const, label: "Endereco" },
  ];

  return (
    <div className="flex items-center justify-center gap-2 sm:gap-4">
      {stepItems.map((item, index) => {
        const active = item.id === step;
        const completed = item.id < step;
        const canGoBack = completed;

        const bubble = (
          <motion.div
            layout
            className="flex items-center justify-center rounded-full border text-sm font-semibold shadow-[0_10px_24px_rgba(15,23,42,0.06)] transition-all duration-200"
            style={{
              width: active ? 52 : 38,
              height: active ? 52 : 38,
              backgroundColor: active ? primaryColor : completed ? "rgba(24,24,27,0.92)" : "#ffffff",
              borderColor: active ? primaryColor : completed ? "rgba(24,24,27,0.92)" : "rgba(228,228,231,1)",
              color: active || completed ? "#ffffff" : "#3f3f46",
            }}
            animate={{ scale: active ? 1 : 0.96 }}
            transition={{ duration: 0.18, ease: "easeOut" }}
          >
            {completed ? <Check className="h-4 w-4" /> : index + 1}
          </motion.div>
        );

        return (
          <div key={item.id} className="flex items-center gap-2 sm:gap-4">
            <div className="flex flex-col items-center gap-2">
              {canGoBack ? (
                <button type="button" onClick={() => onStepChange?.(item.id)} className="rounded-full">
                  {bubble}
                </button>
              ) : (
                bubble
              )}
              <span className={`text-xs font-semibold ${active ? "text-zinc-950" : "text-zinc-400"}`}>
                {item.label}
              </span>
            </div>
            {index < stepItems.length - 1 ? (
              <div className="mb-5 flex items-center gap-2">
                <div className="h-px w-10 bg-zinc-300 sm:w-16" />
                <ChevronRight className="h-4 w-4 text-zinc-400" />
              </div>
            ) : null}
          </div>
        );
      })}
    </div>
  );
}

const inputClass =
  "w-full rounded-xl border border-zinc-200/80 bg-white px-3.5 py-3 text-sm text-zinc-900 outline-none transition placeholder:text-zinc-400 focus:border-zinc-300 focus:ring-4 focus:ring-zinc-100";

function ProfileField({
  label,
  value,
  onChange,
  placeholder,
  maxLength,
  className = "",
  inputMode,
  fieldKey,
  onBlur,
  required = false,
  fieldRef,
}: {
  label: string;
  value: string;
  onChange: (value: string) => void;
  placeholder: string;
  maxLength?: number;
  className?: string;
  inputMode?: React.HTMLAttributes<HTMLInputElement>["inputMode"];
  fieldKey?: string;
  onBlur?: React.FocusEventHandler<HTMLInputElement>;
  required?: boolean;
  fieldRef?: (node: HTMLInputElement | null) => void;
}) {
  return (
    <label className={`space-y-2 ${className}`}>
      <span className="text-sm font-medium text-zinc-700">
        {label}
        {required ? <span className="ml-1 text-rose-500">*</span> : null}
      </span>
      <input
        ref={fieldRef}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        onBlur={onBlur}
        placeholder={placeholder}
        maxLength={maxLength}
        inputMode={inputMode}
        className={inputClass}
      />
    </label>
  );
}

export default function ClientPortalProfileForm({
  slug,
  initial,
  primaryColor = "#18181b", // fallback to zinc-900
  requireComplete = false,
  submitLabel = "Salvar cadastro",
  successMessage = "Cadastro atualizado com sucesso.",
  onSaved,
  onDraftChange,
  step: controlledStep,
  onStepChange,
  showStepper = true,
}: {
  slug: string;
  initial: ClientProfile;
  primaryColor?: string;
  requireComplete?: boolean;
  submitLabel?: string;
  successMessage?: string;
  onSaved?: (profile: ClientProfile) => void;
  onDraftChange?: (profile: ClientProfile) => void;
  step?: OnboardingStep;
  onStepChange?: (step: OnboardingStep) => void;
  showStepper?: boolean;
}) {
  const router = useRouter();
  const [saving, setSaving] = useState(false);
  const [zipLoading, setZipLoading] = useState(false);
  const [error, setError] = useState("");
  const [success, setSuccess] = useState("");
  const [zipError, setZipError] = useState("");
  const [documentError, setDocumentError] = useState("");
  const [internalStep, setInternalStep] = useState<OnboardingStep>(0);
  const step = controlledStep ?? internalStep;
  const setStep = onStepChange ?? setInternalStep;
  const showAllSections = !requireComplete;

  const [form, setForm] = useState({
    name: initial.name || "",
    company_name: initial.company_name || "",
    document: formatDocument(initial.document || ""),
    email: initial.email || "",
    phone: initial.phone || "",
    whatsapp: initial.whatsapp || "",
    address_zip: initial.address_zip || "",
    address_street: initial.address_street || "",
    address_number: initial.address_number || "",
    address_complement: initial.address_complement || "",
    address_neighborhood: initial.address_neighborhood || "",
    address_city: initial.address_city || "",
    address_state: initial.address_state || "",
    notes: initial.notes || "",
  });
  const fieldRefs = useRef<Record<string, HTMLInputElement | HTMLTextAreaElement | null>>({});

  function formatPhone(value: string) {
    const digits = value.replace(/\D/g, "").slice(0, 11);
    if (digits.length <= 2) return digits ? `(${digits}` : "";
    if (digits.length <= 7) return `(${digits.slice(0, 2)}) ${digits.slice(2)}`;
    if (digits.length <= 10) return `(${digits.slice(0, 2)}) ${digits.slice(2, 6)}-${digits.slice(6)}`;
    return `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7)}`;
  }

  function formatZip(value: string) {
    const digits = value.replace(/\D/g, "").slice(0, 8);
    if (digits.length <= 5) return digits;
    return `${digits.slice(0, 5)}-${digits.slice(5)}`;
  }

  function updateField<K extends keyof typeof form>(key: K, value: (typeof form)[K]) {
    setForm((prev) => ({ ...prev, [key]: value }));
    if (key === "address_zip") {
      setZipError("");
    }
    if (key === "document") {
      setDocumentError("");
    }
  }

  const missingFields = useMemo(() => getIncompleteProfileFields(form), [form]);
  const currentStepMissing = useMemo(() => {
    if (step === 0) {
      return missingFields.filter((field) => field === "Nome" || field === "Contato");
    }
    return missingFields.filter((field) =>
      ["CEP", "Rua", "Numero", "Bairro", "Cidade", "UF"].includes(field)
    );
  }, [missingFields, step]);

  function getStepMissing(targetStep: 0 | 1) {
    if (targetStep === 0) {
      return missingFields.filter((field) => field === "Nome" || field === "Contato");
    }
    return missingFields.filter((field) =>
      ["CEP", "Rua", "Numero", "Bairro", "Cidade", "UF"].includes(field)
    );
  }

  function goToNextStep() {
    const stepMissing = getStepMissing(0);
    if (stepMissing.length > 0) {
      setStep(0);
      return;
    }
    setError("");
    setStep(1);
  }

  useEffect(() => {
    // Avoid triggering update when only draft data matches current form
    const isSame = JSON.stringify(form) === JSON.stringify(initial);
    if (!isSame) {
      onDraftChange?.(form);
    }
  }, [form, initial, onDraftChange]);

  async function handleZipLookup(rawZip: string) {
    const zip = String(rawZip || "").replace(/\D/g, "");
    if (zip.length !== 8 || zipLoading) return;

    setZipLoading(true);
    setZipError("");

    try {
      const response = await fetch(`https://viacep.com.br/ws/${zip}/json/`);
      const data = (await response.json()) as {
        erro?: boolean;
        logradouro?: string;
        bairro?: string;
        localidade?: string;
        uf?: string;
      };

      if (!response.ok || data.erro) {
        throw new Error("CEP não encontrado.");
      }

      setForm((prev) => ({
        ...prev,
        address_zip: formatZip(zip),
        address_street: data.logradouro || prev.address_street,
        address_neighborhood: data.bairro || prev.address_neighborhood,
        address_city: data.localidade || prev.address_city,
        address_state: data.uf || prev.address_state,
      }));
    } catch (err) {
      const message =
        typeof err === "object" && err && "message" in err && typeof err.message === "string"
          ? err.message
          : "Não foi possível buscar o CEP.";
      setZipError(message);
    } finally {
      setZipLoading(false);
    }
  }

  async function handleSubmit(event: React.FormEvent) {
    event.preventDefault();
    if (saving) return;
    setSaving(true);
    setError("");
    setSuccess("");
    try {
      const currentMissingFields = requireComplete ? getIncompleteProfileFields(form) : [];
      if (currentMissingFields.length > 0) {
        if (step === 0 && currentMissingFields.some((field) => ["CEP", "Rua", "Numero", "Bairro", "Cidade", "UF"].includes(field))) {
          setStep(1);
        }
        setSaving(false);
        return;
      }

      if (zipError) {
        setSaving(false);
        return;
      }
      if (form.document.trim() && !validateBrazilianDocument(form.document)) {
        setDocumentError(`Informe um ${getDocumentLabel(form.document)} válido.`);
        setSaving(false);
        return;
      }

      const response = await fetch("/api/client-portal/profile", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          slug,
          ...form,
        }),
      });
      const data = (await response.json()) as { error?: string };
      if (!response.ok || data.error) {
        throw new Error(data.error || "Não foi possível salvar seu cadastro.");
      }
      setSuccess(successMessage);
      onSaved?.(form);
      router.refresh();
    } catch (err) {
      const message =
        typeof err === "object" && err && "message" in err && typeof err.message === "string"
          ? err.message
          : "Não foi possível salvar seu cadastro.";
      setError(message);
    } finally {
      setSaving(false);
    }
  }

  return (
    <form onSubmit={handleSubmit} className="space-y-4">
      {requireComplete && showStepper ? (
        <div className="sticky top-0 z-20 -mx-3 border-b border-zinc-200/80 bg-white/96 px-3 py-3 backdrop-blur-xl sm:-mx-5 sm:px-5">
          {showStepper ? <PortalOnboardingStepper step={step} primaryColor={primaryColor} onStepChange={setStep} /> : null}
        </div>
      ) : null}

      <AnimatePresence mode="wait" initial={false}>
        {showAllSections || step === 0 ? (
          <motion.div
            key="step-0"
            initial={{ opacity: 0, x: 28 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: -28 }}
            transition={{ duration: 0.2, ease: "easeOut" }}
            className="space-y-4"
          >
            <section className="rounded-[24px] border border-zinc-200/80 bg-zinc-50/70 p-3.5 sm:p-4">
              <div className="mb-4 flex items-start gap-3">
                <div className="flex h-10 w-10 items-center justify-center rounded-xl border border-zinc-200 bg-white text-zinc-700">
                  <UserCircle2 className="h-4.5 w-4.5" />
                </div>
                <div>
                  <h4 className="text-[15px] font-semibold tracking-[-0.03em] text-zinc-950">
                    Informacoes principais
                  </h4>
                </div>
              </div>
              <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
                <ProfileField
                  label="Nome"
                  value={form.name}
                  onChange={(value) => updateField("name", value)}
                  placeholder="Seu nome completo"
                  fieldKey="name"
                  required
                  fieldRef={(node) => { fieldRefs.current.name = node; }}
                />
                <ProfileField 
                  label="Empresa" 
                  value={form.company_name} 
                  onChange={(value) => updateField("company_name", value)} 
                  placeholder="Opcional" 
                />
                <div className="md:col-span-2">
                  <ProfileField
                    label="CPF ou CNPJ"
                    value={form.document}
                    onChange={(value) => updateField("document", formatDocument(value))}
                    placeholder="000.000.000-00 ou 00.000.000/0000-00"
                    maxLength={18}
                    inputMode="numeric"
                  />
                  {documentError ? (
                    <p className="mt-2 text-xs text-rose-600">{documentError}</p>
                  ) : null}
                </div>
                <ProfileField
                  label="E-mail"
                  value={form.email}
                  onChange={(value) => updateField("email", value)}
                  placeholder="voce@empresa.com.br"
                  inputMode="email"
                />
                <ProfileField
                  label="Telefone"
                  value={form.phone}
                  onChange={(value) => updateField("phone", formatPhone(value))}
                  placeholder="(00) 00000-0000"
                  maxLength={15}
                  inputMode="tel"
                  fieldKey="phone"
                  required
                  fieldRef={(node) => { fieldRefs.current.phone = node; }}
                />
                <ProfileField
                  label="WhatsApp"
                  value={form.whatsapp}
                  onChange={(value) => updateField("whatsapp", formatPhone(value))}
                  placeholder="(00) 00000-0000"
                  maxLength={15}
                  inputMode="tel"
                  fieldKey="whatsapp"
                  required
                  fieldRef={(node) => { fieldRefs.current.whatsapp = node; }}
                />
              </div>
            </section>
          </motion.div>
        ) : null}

        {showAllSections || step === 1 ? (
          <motion.div
            key="step-1"
            initial={{ opacity: 0, x: 28 }}
            animate={{ opacity: 1, x: 0 }}
            exit={{ opacity: 0, x: -28 }}
            transition={{ duration: 0.2, ease: "easeOut" }}
            className="space-y-4"
          >
            <section className="rounded-[24px] border border-zinc-200/80 bg-zinc-50/70 p-3.5 sm:p-4">
              <div className="mb-4 flex items-start gap-3">
                <div className="flex h-10 w-10 items-center justify-center rounded-xl border border-zinc-200 bg-white text-zinc-700">
                  <MapPinned className="h-4.5 w-4.5" />
                </div>
                <div>
                  <h4 className="text-[15px] font-semibold tracking-[-0.03em] text-zinc-950">Endereco</h4>
                </div>
              </div>
              <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
                <label className="space-y-2">
                  <span className="text-sm font-medium text-zinc-700">
                    CEP
                    <span className="ml-1 text-rose-500">*</span>
                  </span>
                  <div className="relative">
                    <input
                      ref={(node) => {
                        fieldRefs.current.address_zip = node;
                      }}
                      value={form.address_zip}
                      onChange={(e) => updateField("address_zip", formatZip(e.target.value))}
                      placeholder="00000-000"
                      maxLength={9}
                      inputMode="numeric"
                      onBlur={(e) => {
                        void handleZipLookup(e.target.value);
                      }}
                      className={`${inputClass} pr-12`}
                    />
                    {zipLoading ? (
                      <span className="pointer-events-none absolute right-4 top-1/2 -translate-y-1/2 text-zinc-400">
                        <LoaderCircle className="h-4 w-4 animate-spin" />
                      </span>
                    ) : null}
                  </div>
                  <div className="text-xs text-zinc-500">Ao informar o CEP, rua, bairro, cidade e UF são preenchidos automaticamente.</div>
                </label>
                <ProfileField
                  label="Rua"
                  value={form.address_street}
                  onChange={(value) => updateField("address_street", value)}
                  placeholder="Nome da rua"
                  fieldKey="address_street"
                  required
                  fieldRef={(node) => { fieldRefs.current.address_street = node; }}
                />
                <ProfileField
                  label="Numero"
                  value={form.address_number}
                  onChange={(value) => updateField("address_number", value)}
                  placeholder="Ex.: 123"
                  fieldKey="address_number"
                  required
                  fieldRef={(node) => { fieldRefs.current.address_number = node; }}
                />
                <ProfileField label="Complemento" value={form.address_complement} onChange={(value) => updateField("address_complement", value)} placeholder="Apartamento, bloco, referencia" />
                <ProfileField
                  label="Bairro"
                  value={form.address_neighborhood}
                  onChange={(value) => updateField("address_neighborhood", value)}
                  placeholder="Seu bairro"
                  fieldKey="address_neighborhood"
                  required
                  fieldRef={(node) => { fieldRefs.current.address_neighborhood = node; }}
                />
                <ProfileField
                  label="Cidade"
                  value={form.address_city}
                  onChange={(value) => updateField("address_city", value)}
                  placeholder="Sua cidade"
                  fieldKey="address_city"
                  required
                  fieldRef={(node) => { fieldRefs.current.address_city = node; }}
                />
                <ProfileField
                  label="UF"
                  value={form.address_state}
                  onChange={(value) => updateField("address_state", value.toUpperCase())}
                  placeholder="UF"
                  maxLength={2}
                  className="md:max-w-[140px]"
                  fieldKey="address_state"
                  required
                  fieldRef={(node) => { fieldRefs.current.address_state = node; }}
                />
              </div>
            </section>

            <section className="rounded-[24px] border border-zinc-200/80 bg-zinc-50/70 p-3.5 sm:p-4">
              <div className="mb-4 flex items-start gap-3">
                <div className="flex h-10 w-10 items-center justify-center rounded-xl border border-zinc-200 bg-white text-zinc-700">
                  <Building2 className="h-4.5 w-4.5" />
                </div>
                <div>
                  <h4 className="text-[15px] font-semibold tracking-[-0.03em] text-zinc-950">Observacoes</h4>
                </div>
              </div>
              <label className="space-y-2">
                <span className="text-sm font-medium text-zinc-700">Notas adicionais</span>
                <textarea
                  ref={(node) => {
                    fieldRefs.current.notes = node;
                  }}
                  value={form.notes}
                  onChange={(e) => updateField("notes", e.target.value)}
                  placeholder="Observacoes"
                  className={`${inputClass} min-h-[110px] resize-y`}
                />
              </label>
            </section>
          </motion.div>
        ) : null}
      </AnimatePresence>

      {error ? (
        <div className="rounded-[18px] border border-rose-200 bg-rose-50 px-3.5 py-2.5 text-sm text-rose-700">
          {error}
        </div>
      ) : null}

      {documentError && !error ? (
        <div className="rounded-[18px] border border-rose-200 bg-rose-50 px-3.5 py-2.5 text-sm text-rose-700">
          {documentError}
        </div>
      ) : null}

      {success ? (
        <div className="rounded-[18px] border border-emerald-200 bg-emerald-50 px-3.5 py-2.5 text-sm text-emerald-700">
          {success}
        </div>
      ) : null}

      <div className="flex flex-col gap-3 rounded-[22px] border border-zinc-200/80 bg-white px-3.5 py-3.5 sm:flex-row sm:items-center sm:justify-between">
        <div className="flex items-start gap-3">
          <div
            className="flex h-10 w-10 shrink-0 items-center justify-center rounded-xl text-white"
            style={{ backgroundColor: primaryColor, color: getReadableTextColor(primaryColor) }}
          >
            <Sparkles className="h-4.5 w-4.5" />
          </div>
          <div className="flex flex-col justify-center">
            <div className="text-sm font-semibold text-zinc-950">Salvar atualizacoes</div>
            <div className="text-xs text-zinc-500">Avance as etapas para salvar</div>
          </div>
        </div>
        <div className="flex w-full flex-col gap-2 sm:w-auto sm:flex-row">
          {requireComplete && step === 1 ? (
            <button
              type="button"
              onClick={() => setStep(0)}
              className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-full border border-zinc-200 px-5 text-sm font-semibold text-zinc-700 transition hover:border-zinc-300 hover:text-zinc-950 sm:w-auto"
            >
              Voltar
            </button>
          ) : null}

          {requireComplete && step === 0 ? (
            <button
              type="button"
              onClick={goToNextStep}
              className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-full border border-transparent px-5 text-sm font-semibold text-white transition-opacity hover:opacity-95 sm:w-auto"
              style={{ backgroundColor: primaryColor, color: getReadableTextColor(primaryColor) }}
            >
              Proxima etapa
              <ChevronRight className="h-4 w-4" />
            </button>
          ) : (
            <button
              type="submit"
              disabled={saving}
              className="inline-flex h-11 w-full items-center justify-center gap-2 rounded-full border border-transparent px-5 text-sm font-semibold text-white transition-opacity hover:opacity-95 disabled:opacity-60 sm:w-auto"
              style={{ backgroundColor: primaryColor, color: getReadableTextColor(primaryColor) }}
            >
              {saving ? <Save className="h-4 w-4 animate-pulse" /> : <Save className="h-4 w-4" />}
              <span className="truncate">{saving ? "Salvando..." : submitLabel}</span>
            </button>
          )}
        </div>
      </div>
    </form>
  );
}
