/**
 * ProfilePage — real My Profile form, wired to backend.
 * Supports all 13 roles. Tabs: Basic Info · Documents.
 * User fills and saves freely; "Submit for Verification" locks and queues for admin.
 */
import { For, Match, Show, Switch, createMemo, createSignal, onMount } from "solid-js";
import {
  CARD,
  BTN_GHOST,
  INPUT,
  LABEL,
  BTN_PRIMARY,
} from "~/components/DashboardShell";
import VerificationSubmissionGuide from "~/components/dashboard/VerificationSubmissionGuide";

const API = "/api/gateway";

const PORTFOLIO_PREFIX: Record<string, string> = {
  PHOTOGRAPHER: "photographers",
  MAKEUP_ARTIST: "makeup-artists",
  TUTOR: "tutors",
  DEVELOPER: "developers",
  VIDEO_EDITOR: "video-editors",
  GRAPHIC_DESIGNER: "graphic-designers",
  SOCIAL_MEDIA_MANAGER: "social-media-managers",
  FITNESS_TRAINER: "fitness-trainers",
  CATERING_SERVICES: "catering-services",
  UGC_CONTENT_CREATOR: "ugc-content-creators",
};

// ── Role-specific field definitions ──────────────────────────────────────────

const BASIC_FIELDS: Record<
  string,
  Array<{ key: string; label: string; type?: string; required?: boolean; options?: string[] }>
> = {
  default: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "location", label: "City", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
    { key: "address", label: "Address", type: "textarea" },
  ],
  COMPANY: [
    { key: "company_name", label: "Company Name", required: true },
    { key: "company_email", label: "Company Email", type: "email", required: true },
    { key: "company_phone", label: "Company Phone" },
    { key: "website", label: "Website URL", type: "url" },
    { key: "location", label: "City", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
    { key: "address", label: "Registered Address", type: "textarea" },
    { key: "gst_number", label: "GST Number (optional)" },
  ],
  PHOTOGRAPHER: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "email", label: "Email Address", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "address_line_1", label: "Address Line 1", required: true },
    { key: "address_line_2", label: "Address Line 2 (Optional)" },
    { key: "city", label: "City", required: true },
    { key: "area", label: "Area", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
  ],
  FITNESS_TRAINER: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    { key: "location", label: "City", required: true },
    { key: "state", label: "State", required: true },
    {
      key: "training_type",
      label: "Training Type",
      type: "select",
      options: [
        "Personal Training",
        "Group Fitness",
        "Yoga",
        "CrossFit",
        "Zumba",
        "Pilates",
        "Other",
      ],
    },
    { key: "experience_years", label: "Years of Experience", type: "number" },
    { key: "bio", label: "Short Bio", type: "textarea" },
  ],
  TUTOR: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    { key: "location", label: "City", required: true },
    { key: "state", label: "State", required: true },
    { key: "subjects", label: "Subjects Taught (comma separated)" },
    { key: "experience_years", label: "Years of Experience", type: "number" },
    { key: "bio", label: "Short Bio", type: "textarea" },
  ],
  CATERING_SERVICES: [
    { key: "business_name", label: "Business Name", required: true },
    { key: "owner_name", label: "Owner Name", required: true },
    { key: "phone", label: "Contact Number", required: true },
    { key: "location", label: "City", required: true },
    { key: "state", label: "State", required: true },
    { key: "cuisine_types", label: "Cuisine Types (comma separated)" },
    { key: "bio", label: "About Your Service", type: "textarea" },
  ],
  MAKEUP_ARTIST: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "email", label: "Email Address", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "address_line_1", label: "Address Line 1", required: true },
    { key: "address_line_2", label: "Address Line 2 (Optional)" },
    { key: "city", label: "City", required: true },
    { key: "area", label: "Area", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
  ],
  DEVELOPER: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "email", label: "Email Address", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "address_line_1", label: "Address Line 1", required: true },
    { key: "address_line_2", label: "Address Line 2 (Optional)" },
    { key: "city", label: "City", required: true },
    { key: "area", label: "Area", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
  ],
  VIDEO_EDITOR: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "email", label: "Email Address", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "address_line_1", label: "Address Line 1", required: true },
    { key: "address_line_2", label: "Address Line 2 (Optional)" },
    { key: "city", label: "City", required: true },
    { key: "area", label: "Area", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
  ],
  UGC_CONTENT_CREATOR: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "email", label: "Email Address", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "address_line_1", label: "Address Line 1", required: true },
    { key: "address_line_2", label: "Address Line 2 (Optional)" },
    { key: "city", label: "City", required: true },
    { key: "area", label: "Area", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
  ],
  GRAPHIC_DESIGNER: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "email", label: "Email Address", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "address_line_1", label: "Address Line 1", required: true },
    { key: "address_line_2", label: "Address Line 2 (Optional)" },
    { key: "city", label: "City", required: true },
    { key: "area", label: "Area", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
  ],
  SOCIAL_MEDIA_MANAGER: [
    { key: "first_name", label: "First Name", required: true },
    { key: "last_name", label: "Last Name", required: true },
    { key: "email", label: "Email Address", required: true },
    { key: "phone", label: "Mobile Number", required: true },
    {
      key: "gender",
      label: "Gender",
      type: "select",
      options: ["Male", "Female", "Other", "Prefer not to say"],
    },
    { key: "address_line_1", label: "Address Line 1", required: true },
    { key: "address_line_2", label: "Address Line 2 (Optional)" },
    { key: "city", label: "City", required: true },
    { key: "area", label: "Area", required: true },
    { key: "state", label: "State", required: true },
    { key: "pin_code", label: "PIN Code" },
  ],
};

const DOC_FIELDS: Record<
  string,
  Array<{ key: string; label: string; required?: boolean; hint?: string }>
> = {
  default: [
    {
      key: "aadhar_doc",
      label: "Aadhar / Government ID",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
  ],
  COMPANY: [
    {
      key: "registration_doc",
      label: "Company Registration Certificate",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    { key: "gst_doc", label: "GST Certificate (optional)", hint: "JPG, PNG or PDF · Max 10MB" },
  ],
  PHOTOGRAPHER: [
    {
      key: "aadhar_doc",
      label: "Identity Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "address_proof",
      label: "Address Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "portfolio_ownership_proof",
      label: "Portfolio Ownership Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
  ],
  MAKEUP_ARTIST: [
    {
      key: "aadhar_doc",
      label: "Identity Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "address_proof",
      label: "Address Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "professional_certifications",
      label: "Professional Certifications",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
  ],
  TUTOR: [
    {
      key: "aadhar_doc",
      label: "Identity Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "address_proof",
      label: "Address Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "qualification_proof",
      label: "Qualification Proof",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
  ],
  FITNESS_TRAINER: [
    {
      key: "aadhar_doc",
      label: "Aadhar / Government ID",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "certification_doc",
      label: "Fitness Certification",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
  ],
  CATERING_SERVICES: [
    {
      key: "aadhar_doc",
      label: "Aadhar / Government ID",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
    {
      key: "fssai_license",
      label: "FSSAI License",
      required: true,
      hint: "JPG, PNG or PDF · Max 10MB",
    },
  ],
};

function getBasicFields(roleKey: string) {
  return BASIC_FIELDS[roleKey] ?? BASIC_FIELDS.default;
}
function getDocFields(roleKey: string) {
  return DOC_FIELDS[roleKey] ?? DOC_FIELDS.default;
}
function applyRuntimeFields<T extends { key: string }>(fields: T[], runtimeFields?: string[]): T[] {
  if (!runtimeFields || runtimeFields.length === 0) return fields;
  const fieldMap = new Map(fields.map(f => [f.key, f]));
  return runtimeFields
    .filter(key => fieldMap.has(key))
    .map(key => fieldMap.get(key)!);
}

function resolveRuntimeFieldKeys(runtimeFields?: string[]): string[] {
  if (!runtimeFields || runtimeFields.length === 0) return [];
  const FIELD_KEY_MAP: Record<string, string> = {
    full_name: 'first_name',
    email: 'email',
    phone: 'phone',
    location: 'city',
    verification_status: '',
    approval_status: '',
  };
  const resolved: string[] = [];
  for (const key of runtimeFields) {
    const mapped = FIELD_KEY_MAP[key];
    if (mapped) resolved.push(mapped);
  }
  return resolved;
}

// ── Helpers ───────────────────────────────────────────────────────────────────

async function apiFetch(path: string, opts?: RequestInit) {
  const token =
    typeof window !== "undefined"
      ? window.sessionStorage.getItem("nxtgauge_access_token") || ""
      : "";
  return fetch(`${API}${path}`, {
    ...opts,
    credentials: "include",
    headers: {
      "Content-Type": "application/json",
      ...(token ? { Authorization: `Bearer ${token}` } : {}),
      ...(opts?.headers ?? {}),
    },
  });
}

// ── Component ─────────────────────────────────────────────────────────────────

interface Props {
  roleKey: string;
  runtimeFields?: string[];
  onVerificationStatusChange?: (status: string) => void;
}

type Tab = "basic" | "documents";

export default function ProfilePage(props: Props) {
  const [tab, setTab] = createSignal<Tab>("basic");
  const [form, setForm] = createSignal<Record<string, string>>({});
  const [saving, setSaving] = createSignal(false);
  const [saveMsg, setSaveMsg] = createSignal("");
  const [verificationStatus, setVerificationStatus] = createSignal("NOT_SUBMITTED");
  const [docRequest, setDocRequest] = createSignal<string | null>(null);
  const [submitting, setSubmitting] = createSignal(false);
  const [submitMsg, setSubmitMsg] = createSignal("");
  const [missingPortfolioLabels, setMissingPortfolioLabels] = createSignal<string[]>([]);

  const requiresPortfolio = () => props.roleKey === "JOB_SEEKER" || Boolean(PORTFOLIO_PREFIX[props.roleKey]);

  const refreshPortfolioSubmission = async (): Promise<string[]> => {
    if (props.roleKey === "JOB_SEEKER") {
      const missing: string[] = [];
      try {
        const res = await apiFetch("/api/jobseeker/profile/me");
        if (!res.ok) {
          setMissingPortfolioLabels(["Portfolio details"]);
          return ["Portfolio details"];
        }
        const data = await res.json().catch(() => ({}));
        const portfolio = data?.custom_data?.job_seeker_portfolio || {};
        if (!String(portfolio?.headline || "").trim()) missing.push("Professional headline");
        if (!String(portfolio?.summary || "").trim()) missing.push("Career summary");
        if (!String(portfolio?.education || "").trim()) missing.push("Education");
        if (!String(portfolio?.workExperience || "").trim()) missing.push("Work experience");
        if (!String(portfolio?.skills || "").trim()) missing.push("Skills");
      } catch {
        missing.push("Portfolio details");
      }
      setMissingPortfolioLabels(missing);
      return missing;
    }

    if (!requiresPortfolio()) {
      setMissingPortfolioLabels([]);
      return [];
    }

    const missing: string[] = [];
    const roleStorageKey = `nxtgauge_portfolio_meta_${String(props.roleKey || "professional").toLowerCase()}`;

    let meta: any = {};
    if (typeof window !== "undefined") {
      try {
        const raw = window.localStorage.getItem(roleStorageKey);
        meta = raw ? JSON.parse(raw) : {};
      } catch {
        meta = {};
      }
    }

    const aboutDone = String(meta?.about || "").trim().length > 0;
    const servicesDone = Array.isArray(meta?.services)
      ? meta.services.some((s: any) =>
          String(s?.name || "").trim() || String(s?.amount || "").trim() || String(s?.details || "").trim()
        )
      : false;
    const experienceDone = Array.isArray(meta?.experience)
      ? meta.experience.some((e: any) => String(e?.year || "").trim() || String(e?.description || "").trim())
      : false;
    const toolsDone = Array.isArray(meta?.tools) ? meta.tools.some((t: any) => String(t || "").trim()) : false;
    const faqDone = Array.isArray(meta?.faqs)
      ? meta.faqs.some((f: any) => String(f?.question || "").trim() && String(f?.answer || "").trim())
      : false;

    if (!aboutDone) missing.push("About");
    if (!servicesDone) missing.push("Services & pricing");
    if (!experienceDone && !toolsDone) missing.push("Experience / tools");
    if (!faqDone) missing.push("FAQs");

    try {
      const res = await apiFetch(`/api/${PORTFOLIO_PREFIX[props.roleKey]}/portfolio/me`);
      if (!res.ok) {
        missing.push("Showcase items");
        setMissingPortfolioLabels(Array.from(new Set(missing)));
        return Array.from(new Set(missing));
      }
      const data = await res.json().catch(() => []);
      const items = Array.isArray(data) ? data : data?.items ?? [];
      if (!Array.isArray(items) || items.length === 0) missing.push("Showcase items");
    } catch {
      missing.push("Showcase items");
    }

    const uniqueMissing = Array.from(new Set(missing));
    setMissingPortfolioLabels(uniqueMissing);
    return uniqueMissing;
  };

  // Load saved profile + verification status on mount
  onMount(async () => {
    const [profileRes, statusRes] = await Promise.all([
      apiFetch(`/api/profile?roleKey=${props.roleKey}`),
      apiFetch(`/api/me/verification-status?roleKey=${props.roleKey}`),
    ]);

    if (profileRes.ok) {
      const data = await profileRes.json();
      if (data.profile_data && typeof data.profile_data === "object") {
        const flat: Record<string, string> = {};
        for (const [k, v] of Object.entries(data.profile_data)) {
          flat[k] = String(v ?? "");
        }
        setForm(flat);
      }
    }

    if (statusRes.ok) {
      const s = await statusRes.json();
      const nextStatus = String(s.status ?? "NOT_SUBMITTED");
      setVerificationStatus(nextStatus);
      props.onVerificationStatusChange?.(nextStatus);
      setDocRequest(s.document_request ?? null);
    }

    void refreshPortfolioSubmission();
  });

  const isLocked = () => ["PENDING", "UNDER_REVIEW"].includes(verificationStatus());

  const setField = (key: string, val: string) => setForm((prev) => ({ ...prev, [key]: val }));

  const handleSave = async () => {
    setSaving(true);
    setSaveMsg("");
    try {
      const res = await apiFetch("/api/profile", {
        method: "PATCH",
        body: JSON.stringify({ roleKey: props.roleKey, profile_data: form() }),
      });
      setSaveMsg(res.ok ? "Saved successfully." : "Failed to save. Please try again.");
    } catch {
      setSaveMsg("Network error. Please try again.");
    } finally {
      setSaving(false);
      setTimeout(() => setSaveMsg(""), 3000);
    }
  };

  const handleSubmitForVerification = async () => {
    const portfolioMissing = await refreshPortfolioSubmission();
    if (missingBasicLabels().length > 0 || missingDocLabels().length > 0 || portfolioMissing.length > 0) {
      if (missingBasicLabels().length > 0) {
        setTab("basic");
        setSubmitMsg(`Complete required profile fields before submitting: ${missingBasicLabels().join(", ")}`);
      } else if (missingDocLabels().length > 0) {
        setTab("documents");
        setSubmitMsg(`Upload required documents before submitting: ${missingDocLabels().join(", ")}`);
      } else {
        setSubmitMsg(`Complete portfolio before submitting: ${portfolioMissing.join(", ")}. Go to My Portfolio.`);
      }
      return;
    }
    setSubmitting(true);
    setSubmitMsg("");
    try {
      const res = await apiFetch("/api/profile/submit-for-verification", {
        method: "POST",
        body: JSON.stringify({ roleKey: props.roleKey }),
      });
      const data = await res.json();
      if (res.ok) {
        setVerificationStatus("PENDING");
        props.onVerificationStatusChange?.("PENDING");
        setSubmitMsg("Submitted! We will review your profile and notify you.");
      } else if (res.status === 409) {
        setSubmitMsg(data.error ?? "A verification is already in progress.");
      } else {
        setSubmitMsg(data.error ?? "Submission failed. Please try again.");
      }
    } catch {
      setSubmitMsg("Network error. Please try again.");
    } finally {
      setSubmitting(false);
    }
  };

  const statusColor: Record<string, string> = {
    PENDING: "#F59E0B",
    UNDER_REVIEW: "#3B82F6",
    DOCUMENTS_REQUESTED: "#FF5E13",
    REVISION_REQUESTED: "#FF5E13",
    APPROVED: "#10B981",
    REJECTED: "#EF4444",
    NOT_SUBMITTED: "#9CA3AF",
  };

  const statusLabel: Record<string, string> = {
    PENDING: "Pending Review",
    UNDER_REVIEW: "Under Review",
    DOCUMENTS_REQUESTED: "Documents Requested",
    REVISION_REQUESTED: "Revision Requested",
    APPROVED: "Approved",
    REJECTED: "Rejected",
    NOT_SUBMITTED: "Not Submitted",
  };

  const basicFields = createMemo(() =>
    applyRuntimeFields(getBasicFields(props.roleKey), resolveRuntimeFieldKeys(props.runtimeFields))
  );
  const requiredBasicFields = createMemo(() => basicFields().filter((field) => field.required));
  const requiredDocFields = createMemo(() => getDocFields(props.roleKey).filter((doc) => doc.required));
  const missingBasicLabels = createMemo(() =>
    requiredBasicFields()
      .filter((field) => !String(form()[field.key] || "").trim())
      .map((field) => field.label)
  );
  const missingDocLabels = createMemo(() =>
    requiredDocFields()
      .filter((doc) => !String(form()[doc.key] || "").trim())
      .map((doc) => doc.label)
  );
  const canSubmitVerification = createMemo(
    () =>
      !isLocked() &&
      verificationStatus() !== "APPROVED" &&
      missingBasicLabels().length === 0 &&
      missingDocLabels().length === 0 &&
      missingPortfolioLabels().length === 0
  );

  return (
    <div style={{ "max-width": "760px" }}>
      <VerificationSubmissionGuide
        statusLabel={statusLabel[verificationStatus()] ?? verificationStatus()}
        statusColor={statusColor[verificationStatus()] ?? "#9CA3AF"}
        locked={isLocked()}
        approved={verificationStatus() === "APPROVED"}
        docRequest={docRequest()}
        missingBasicLabels={missingBasicLabels()}
        missingDocLabels={missingDocLabels()}
        missingPortfolioLabels={missingPortfolioLabels()}
        canSubmit={canSubmitVerification()}
        submitting={submitting()}
        onSubmit={handleSubmitForVerification}
        onGoBasic={() => setTab("basic")}
        onGoDocuments={() => setTab("documents")}
      />

      <Show when={submitMsg()}>
        <div
          style={{
            ...CARD,
            "margin-bottom": "16px",
            padding: "12px 16px",
            background: submitMsg().includes("Submitted") ? "#ECFDF5" : "#FEF2F2",
            border: `1px solid ${submitMsg().includes("Submitted") ? "#6EE7B7" : "#FECACA"}`,
            color: submitMsg().includes("Submitted") ? "#065F46" : "#B91C1C",
            "font-size": "13px",
            "font-weight": "600",
          }}
        >
          {submitMsg()}
        </div>
      </Show>

      {/* ── Tabs ──────────────────────────────────────────────────────── */}
      <div style={{ display: "flex", gap: "0px", "margin-bottom": "16px", "border-bottom": "1px solid #E5E7EB" }}>
        <For
          each={
            [
              { key: "basic", label: "Basic Information" },
              { key: "documents", label: "Documents" },
            ] as Array<{ key: Tab; label: string }>
          }
        >
          {(t) => (
            <button
              type="button"
              onClick={() => setTab(t.key)}
              style={{
                height: "44px",
                padding: "0 16px",
                "border-radius": "0px",
                border: "none",
                "border-bottom": tab() === t.key ? "2px solid #FF5E13" : "2px solid transparent",
                background: "transparent",
                color: tab() === t.key ? "#FF5E13" : "#6B7280",
                "font-size": "14px",
                "font-weight": tab() === t.key ? "700" : "500",
                cursor: "pointer",
                "margin-bottom": "-1px",
              }}
            >
              {t.label}
            </button>
          )}
        </For>
      </div>

      {/* ── Tab content ───────────────────────────────────────────────── */}
      <div style={CARD}>
        <Switch>
          {/* Basic Info */}
          <Match when={tab() === "basic"}>
            <div style={{ display: "grid", "grid-template-columns": "1fr 1fr", gap: "10px" }}>
              <For each={basicFields()}>
                {(field) => (
                  <div style={{ "grid-column": field.type === "textarea" ? "span 2" : "span 1" }}>
                    <label style={LABEL}>
                      {field.label}
                      <Show when={field.required}>
                        <span style={{ color: "#EF4444" }}> *</span>
                      </Show>
                    </label>
                    <Switch>
                      <Match when={field.type === "textarea"}>
                        <textarea
                          rows={3}
                          disabled={isLocked()}
                          value={form()[field.key] ?? ""}
                          onInput={(e) => setField(field.key, e.currentTarget.value)}
                          style={{
                            ...INPUT,
                            height: "auto",
                            padding: "10px 12px",
                            resize: "vertical",
                            opacity: isLocked() ? "0.6" : "1",
                          }}
                        />
                      </Match>
                      <Match when={field.type === "select"}>
                        <select
                          disabled={isLocked()}
                          value={form()[field.key] ?? ""}
                          onChange={(e) => setField(field.key, e.currentTarget.value)}
                          style={{ ...INPUT, opacity: isLocked() ? "0.6" : "1" }}
                        >
                          <option value="">Select…</option>
                          <For each={field.options ?? []}>
                            {(opt) => <option value={opt}>{opt}</option>}
                          </For>
                        </select>
                      </Match>
                      <Match when={true}>
                        <input
                          type={field.type ?? "text"}
                          disabled={isLocked()}
                          value={form()[field.key] ?? ""}
                          onInput={(e) => setField(field.key, e.currentTarget.value)}
                          style={{ ...INPUT, opacity: isLocked() ? "0.6" : "1" }}
                        />
                      </Match>
                    </Switch>
                  </div>
                )}
              </For>
            </div>

            <Show when={isLocked()}>
              <p style={{ margin: "16px 0 0", "font-size": "12px", color: "#9CA3AF" }}>
                Profile is locked while verification is in progress.
              </p>
            </Show>
          </Match>

          {/* Documents */}
          <Match when={tab() === "documents"}>
            <div style={{ display: "flex", "flex-direction": "column", gap: "16px" }}>
              <For each={getDocFields(props.roleKey)}>
                {(doc) => (
                  <div
                    style={{
                      border: "1px dashed #E5E7EB",
                      "border-radius": "10px",
                      padding: "16px",
                    }}
                  >
                    <p
                      style={{
                        margin: "0",
                        "font-size": "13px",
                        "font-weight": "700",
                        color: "#111827",
                      }}
                    >
                      {doc.label}
                      <Show when={doc.required}>
                        <span style={{ color: "#EF4444" }}> *</span>
                      </Show>
                    </p>
                    <Show when={doc.hint}>
                      <p style={{ margin: "2px 0 10px", "font-size": "11px", color: "#9CA3AF" }}>
                        {doc.hint}
                      </p>
                    </Show>
                    <Show
                      when={form()[doc.key]}
                      fallback={
                        <div style={{ display: "flex", "align-items": "center", gap: "10px" }}>
                          <input
                            type="file"
                            id={`file-${doc.key}`}
                            style={{ display: "none" }}
                            disabled={isLocked()}
                            onChange={(e) => {
                              const file = e.currentTarget.files?.[0];
                              if (file) setField(doc.key, file.name);
                            }}
                          />
                          <label
                            for={`file-${doc.key}`}
                            style={{
                              ...BTN_GHOST,
                              display: "inline-flex",
                              "align-items": "center",
                              "line-height": "1",
                              opacity: isLocked() ? "0.5" : "1",
                              cursor: isLocked() ? "not-allowed" : "pointer",
                            }}
                          >
                            Choose File
                          </label>
                          <span style={{ "font-size": "12px", color: "#9CA3AF" }}>
                            No file chosen
                          </span>
                        </div>
                      }
                    >
                      <div style={{ display: "flex", "align-items": "center", gap: "10px" }}>
                        <span
                          style={{
                            "font-size": "12px",
                            "font-weight": "600",
                            color: "#10B981",
                            background: "#ECFDF5",
                            padding: "4px 10px",
                            "border-radius": "6px",
                          }}
                        >
                          ✓ {form()[doc.key]}
                        </span>
                        <Show when={!isLocked()}>
                          <button
                            type="button"
                            onClick={() => setField(doc.key, "")}
                            style={{
                              ...BTN_GHOST,
                              height: "28px",
                              "font-size": "11px",
                              padding: "0 10px",
                            }}
                          >
                            Remove
                          </button>
                        </Show>
                      </div>
                    </Show>
                  </div>
                )}
              </For>
            </div>
          </Match>
        </Switch>
      </div>

      {/* ── Save button ─────────────────────────────────────────────── */}
      <div style={{ display: "flex", "align-items": "center", gap: "12px", "margin-top": "16px" }}>
        <button
          type="button"
          onClick={handleSave}
          disabled={saving() || isLocked()}
          style={{ ...BTN_PRIMARY, opacity: saving() || isLocked() ? "0.6" : "1" }}
        >
          {saving() ? "Saving…" : "Save Changes"}
        </button>
        <Show when={saveMsg()}>
          <span
            style={{
              "font-size": "13px",
              "font-weight": "600",
              color: saveMsg().includes("success") ? "#10B981" : "#EF4444",
            }}
          >
            {saveMsg()}
          </span>
        </Show>
      </div>
    </div>
  );
}
