/**
 * RoleWizard — schema-driven verification wizard, generalized from the
 * COMPANY-only 3-step wizard that used to live inline in ProfilePage.tsx.
 * Steps/fields/lock-after-approval flags come from the role's active
 * onboarding_configs schema (admin-editable via the Onboarding Schema Editor),
 * fetched through fetchOnboardingSchemaForRole() — nothing here is
 * per-role-hardcoded.
 *
 * COMPANY keeps using the separate CompanyWizard component (still in
 * ProfilePage.tsx) since its documents step submits via a dedicated bulk
 * multipart endpoint (submitCompanyProfileWithDocuments) rather than the
 * per-file immediate-upload flow every other role's document endpoints use.
 *
 * Pre-fill (shared identity docs):
 *   Pass `prefilledDocs` — a map of fieldId → already-uploaded URL — to
 *   pre-populate identity fields (Aadhaar, PAN, selfie, etc.) that the user
 *   already submitted for another role.  Fields are pre-filled when they are
 *   marked `identity_shared: true` in the schema OR their ID matches
 *   CONVENTION_IDENTITY_FIELD_IDS.  The user can always click "Change" to
 *   re-upload.
 */
import { For, Match, Show, Switch, createMemo, createSignal, onMount } from "solid-js";
import { CARD, BTN_GHOST, INPUT, LABEL, BTN_PRIMARY } from "~/components/DashboardShell";
import { request, uploadDocument } from "~/lib/api";
import { updateJobSeekerCustomData } from "~/lib/job-seeker-custom-data";
import { fetchOnboardingSchemaForRole } from "~/lib/runtime/storage";
import { isIdentityField } from "~/lib/role-utils";
import type { RuntimeOnboardingConfig, RuntimeOnboardingField, RuntimeOnboardingStep } from "~/lib/runtime/types";

interface Props {
  roleKey: string;
  rolePrefix: string; // e.g. "job-seekers", "photographers" — matches the role's document-upload API path
  /** Pre-filled doc URLs from the user's existing role profile. fieldId → url */
  prefilledDocs?: Record<string, string>;
  onSubmitted: (status: string) => void;
}

/** Props for the reusable file-upload control sub-component. */
interface FileControlProps {
  field: RuntimeOnboardingField;
  inputId: string;
  isReused: boolean;
  hasUrl: boolean;
  uploading: boolean;
  error: string;
  onFileChange: (file: File) => void;
}

/**
 * A self-contained file-upload control rendered as a proper SolidJS component
 * so that reactivity from parent signals flows correctly through its props.
 */
function FileControl(props: FileControlProps) {
  return (
    <>
      <input
        type="file"
        id={props.inputId}
        style={{ display: "none" }}
        accept={props.field.accept}
        multiple={props.field.multiple}
        disabled={props.uploading}
        onChange={(e) => {
          const file = e.currentTarget.files?.[0];
          if (file) props.onFileChange(file);
          e.currentTarget.value = "";
        }}
      />
      <Show
        when={props.hasUrl}
        fallback={
          <div style={{ display: "flex", "align-items": "center", gap: "10px", "flex-wrap": "wrap" }}>
            <label
              for={props.inputId}
              style={{ ...BTN_GHOST, display: "inline-flex", "align-items": "center", "line-height": "1", cursor: props.uploading ? "not-allowed" : "pointer", opacity: props.uploading ? 0.6 : 1 }}
            >
              {props.uploading ? "Uploading…" : "Choose File"}
            </label>
            <span style={{ "font-size": "12px", color: "#9CA3AF" }}>No file chosen</span>
            <Show when={props.error}>
              <p style={{ margin: "4px 0 0", "font-size": "11px", color: "#EF4444", width: "100%" }}>{props.error}</p>
            </Show>
          </div>
        }
      >
        <div style={{ display: "flex", "align-items": "center", gap: "8px", "flex-wrap": "wrap" }}>
          <Show
            when={props.isReused}
            fallback={
              <span style={{ "font-size": "12px", "font-weight": "600", color: "#10B981", background: "#ECFDF5", padding: "4px 10px", "border-radius": "6px" }}>
                ✓ Uploaded
              </span>
            }
          >
            <span style={{ "font-size": "12px", "font-weight": "600", color: "#6366F1", background: "#EEF2FF", padding: "4px 10px", "border-radius": "6px" }}>
              ♻ Reused from your existing profile
            </span>
          </Show>
          <label
            for={props.inputId}
            style={{ "font-size": "12px", color: "#6B7280", "text-decoration": "underline", cursor: "pointer" }}
          >
            Change
          </label>
        </div>
      </Show>
    </>
  );
}

function fieldRequired(field: RuntimeOnboardingField): boolean {
  return Boolean(field.required);
}

export default function RoleWizard(props: Props) {
  const [config, setConfig] = createSignal<RuntimeOnboardingConfig | null>(null);
  const [loading, setLoading] = createSignal(true);
  const [wizardStep, setWizardStep] = createSignal(0);
  const [form, setForm] = createSignal<Record<string, string>>({});
  const [docUrls, setDocUrls] = createSignal<Record<string, string>>({});
  /** Tracks which doc fields were pre-filled from another role (shown with reuse badge). */
  const [reusedDocs, setReusedDocs] = createSignal<Set<string>>(new Set());
  const [docErrors, setDocErrors] = createSignal<Record<string, string>>({});
  const [docUploading, setDocUploading] = createSignal<Record<string, boolean>>({});
  const [portfolioForm, setPortfolioForm] = createSignal<Record<string, string>>({});
  const [submitting, setSubmitting] = createSignal(false);
  const [submitMsg, setSubmitMsg] = createSignal("");
  const [submitSuccess, setSubmitSuccess] = createSignal(false);

  onMount(async () => {
    const cfg = await fetchOnboardingSchemaForRole(props.roleKey);
    setConfig(cfg);

    // Pre-fill shared identity docs passed in from SwitchServicesPage
    if (props.prefilledDocs && cfg) {
      const preUrls: Record<string, string> = {};
      const reused = new Set<string>();

      for (const step of cfg.steps) {
        for (const field of step.fields) {
          if (field.type !== "file") continue;
          if (!isIdentityField(field.id, Boolean(field.identity_shared))) continue;
          const existingUrl = props.prefilledDocs[field.id];
          if (existingUrl) {
            preUrls[field.id] = existingUrl;
            reused.add(field.id);
          }
        }
      }

      if (Object.keys(preUrls).length > 0) {
        setDocUrls(preUrls);
        setReusedDocs(reused);
      }
    }

    setLoading(false);
  });

  const steps = createMemo<RuntimeOnboardingStep[]>(() => config()?.steps ?? []);
  const currentStep = createMemo(() => steps()[wizardStep()]);

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

  const stepIsComplete = (step: RuntimeOnboardingStep | undefined): boolean => {
    if (!step) return true;
    if (step.type === "documents") {
      return step.fields.filter(fieldRequired).every((f) => Boolean(docUrls()[f.id]));
    }
    if (step.type === "portfolio") {
      return step.fields.filter(fieldRequired).every((f) => String(portfolioForm()[f.id] ?? "").trim().length > 0);
    }
    if (step.type === "review") return true;
    // basic — file fields are tracked in docUrls, not form
    return step.fields.filter(fieldRequired).every((f) => {
      if (f.type === "file") return Boolean(docUrls()[f.id]);
      return String(form()[f.id] ?? "").trim().length > 0;
    });
  };

  const canAdvance = createMemo(() => stepIsComplete(currentStep()));

  const handleFileSelect = async (field: RuntimeOnboardingField, file: File) => {
    setDocUploading((prev) => ({ ...prev, [field.id]: true }));
    setDocErrors((prev) => ({ ...prev, [field.id]: "" }));
    // Once the user uploads a new file, it's no longer "reused"
    setReusedDocs((prev) => { const next = new Set(prev); next.delete(field.id); return next; });
    try {
      const result = await uploadDocument(props.rolePrefix, file, field.id);
      const url = result?.url ?? result?.file_url ?? result?.path ?? result?.file_name ?? "uploaded";
      setDocUrls((prev) => ({ ...prev, [field.id]: url }));
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : "Upload failed";
      setDocErrors((prev) => ({ ...prev, [field.id]: msg }));
    } finally {
      setDocUploading((prev) => ({ ...prev, [field.id]: false }));
    }
  };

  const savePortfolio = async (portfolioSnapshot: Record<string, string>) => {
    const model = config()?.portfolioModel;
    if (!model || model === "none") return;
    if (model === "custom_data") {
      await updateJobSeekerCustomData((current) => ({ ...current, job_seeker_portfolio: portfolioSnapshot }));
    } else if (model === "professional") {
      await request("/api/profile", {
        method: "PATCH",
        body: { roleKey: props.roleKey, profile_data: portfolioSnapshot },
      }).catch(() => undefined);
    }
  };

  const handleSubmit = async () => {
    setSubmitting(true);
    setSubmitMsg("");
    // Snapshot all reactive values synchronously before the first await
    const portfolioSnapshot = portfolioForm();
    const profile_data = { ...form(), ...docUrls() };
    try {
      await savePortfolio(portfolioSnapshot);
      await request("/api/profile", { method: "PATCH", body: { roleKey: props.roleKey, profile_data } });
      const { status } = await request("/api/profile/submit-for-verification", {
        method: "POST",
        body: { roleKey: props.roleKey, profile_data },
      });
      if (status === 200 || status === 201) {
        setSubmitSuccess(true);
        setTimeout(() => props.onSubmitted("PENDING"), 2500);
      }
    } catch (err: unknown) {
      const msg = err instanceof Error ? err.message : "Submission failed. Please try again.";
      setSubmitMsg(msg);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Show when={!loading()} fallback={<p style={{ "font-size": "13px", color: "#6B7280" }}>Loading...</p>}>
      <Show
        when={config() && steps().length > 0}
        fallback={
          <p style={{ "font-size": "13px", color: "#6B7280" }}>
            No verification wizard is configured for this role yet.
          </p>
        }
      >
        <div>
          <Show when={submitSuccess()}>
            <div style={{ ...CARD, "margin-bottom": "16px", padding: "24px", background: "#ECFDF5", border: "1px solid #6EE7B7", "text-align": "center" }}>
              <div style={{ "font-size": "36px", "margin-bottom": "8px" }}>✓</div>
              <h3 style={{ margin: "0 0 8px", "font-size": "18px", color: "#065F46" }}>Submitted!</h3>
              <p style={{ margin: "0 0 16px", "font-size": "13px", color: "#065F46" }}>
                We'll review your profile and notify you once it's checked.
              </p>
            </div>
          </Show>

          <Show when={!submitSuccess()}>
            {/* ── Stepper ─────────────────────────────────────────────── */}
            <div style={{ display: "flex", "align-items": "center", gap: "8px", "margin-bottom": "24px" }}>
              <For each={steps()}>
                {(step, i) => (
                  <>
                    <div
                      style={{
                        width: "32px", height: "32px", "border-radius": "50%",
                        display: "flex", "align-items": "center", "justify-content": "center",
                        "font-weight": "700", "font-size": "14px",
                        background: wizardStep() === i() ? "#FF5E13" : wizardStep() > i() ? "#FFF" : "#F3F4F6",
                        color: wizardStep() === i() ? "#FFF" : wizardStep() > i() ? "#FF5E13" : "#9CA3AF",
                        border: wizardStep() >= i() ? "2px solid #FF5E13" : "2px solid #E5E7EB",
                      }}
                    >
                      {wizardStep() > i() ? "✓" : i() + 1}
                    </div>
                    <Show when={i() < steps().length - 1}>
                      <div style={{ flex: 1, height: "2px", background: wizardStep() > i() ? "#FF5E13" : "#E5E7EB" }} />
                    </Show>
                  </>
                )}
              </For>
            </div>
            <p style={{ "font-size": "13px", color: "#6B7280", "margin-bottom": "16px" }}>
              Step {wizardStep() + 1} of {steps().length} — {currentStep()?.title}
            </p>

            <div style={CARD}>
              {/* ── basic ─────────────────────────────────────────────── */}
              <Show when={(currentStep()?.type === "basic" || !currentStep()?.type) && (currentStep()?.fields?.length ?? 0) === 0}>
                <p style={{ "font-size": "13px", color: "#9CA3AF" }}>This step has no fields configured yet.</p>
              </Show>
              <Show when={(currentStep()?.type === "basic" || !currentStep()?.type) && (currentStep()?.fields?.length ?? 0) > 0}>
                <div style={{ display: "grid", "grid-template-columns": "1fr 1fr", gap: "10px" }}>
                  <For each={currentStep()?.fields ?? []}>
                    {(field) => (
                      <div style={{ "grid-column": (field.type === "textarea" || field.type === "file") ? "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}
                              value={form()[field.id] ?? ""}
                              onInput={(e) => setField(field.id, e.currentTarget.value)}
                              style={{ ...INPUT, height: "auto", padding: "10px 12px", resize: "vertical" }}
                            />
                          </Match>
                          <Match when={field.type === "select"}>
                            <select value={form()[field.id] ?? ""} onChange={(e) => setField(field.id, e.currentTarget.value)} style={{ ...INPUT }}>
                              <option value="">Select…</option>
                              <For each={field.options ?? []}>{(opt) => <option value={opt.value}>{opt.label}</option>}</For>
                            </select>
                          </Match>
                          <Match when={field.type === "file"}>
                            <FileControl
                              field={field}
                              inputId={`rw-file-basic-${field.id}`}
                              isReused={reusedDocs().has(field.id)}
                              hasUrl={Boolean(docUrls()[field.id])}
                              uploading={Boolean(docUploading()[field.id])}
                              error={docErrors()[field.id] ?? ""}
                              onFileChange={
                                // eslint-disable-next-line solid/reactivity
                                (file) => void handleFileSelect(field, file)
                              }
                            />
                          </Match>
                          <Match when={true}>
                            <input
                              type={field.type ?? "text"}
                              value={form()[field.id] ?? ""}
                              onInput={(e) => setField(field.id, e.currentTarget.value)}
                              style={{ ...INPUT }}
                            />
                          </Match>
                        </Switch>
                      </div>
                    )}
                  </For>
                </div>
              </Show>

              {/* ── documents ─────────────────────────────────────────── */}
              <Show when={currentStep()?.type === "documents" && (currentStep()?.fields?.length ?? 0) === 0}>
                <p style={{ "font-size": "13px", color: "#9CA3AF" }}>This step has no documents configured yet.</p>
              </Show>
              <Show when={currentStep()?.type === "documents" && (currentStep()?.fields?.length ?? 0) > 0}>
                <div style={{ display: "flex", "flex-direction": "column", gap: "16px" }}>
                  <For each={currentStep()?.fields ?? []}>
                    {(field) => (
                      <div style={{ border: "1px dashed #E5E7EB", "border-radius": "10px", padding: "16px" }}>
                        <p style={{ margin: "0", "font-size": "13px", "font-weight": "700", color: "#111827" }}>
                          {field.label}
                          <Show when={field.required}><span style={{ color: "#EF4444" }}> *</span></Show>
                        </p>
                        <Show when={field.helperText}>
                          <p style={{ margin: "2px 0 10px", "font-size": "11px", color: "#9CA3AF" }}>{field.helperText}</p>
                        </Show>
                        <FileControl
                          field={field}
                          inputId={`rw-file-${field.id}`}
                          isReused={reusedDocs().has(field.id)}
                          hasUrl={Boolean(docUrls()[field.id])}
                          uploading={Boolean(docUploading()[field.id])}
                          error={docErrors()[field.id] ?? ""}
                          onFileChange={
                            // eslint-disable-next-line solid/reactivity
                            (file) => void handleFileSelect(field, file)
                          }
                        />
                      </div>
                    )}
                  </For>
                </div>
              </Show>

              {/* ── portfolio ─────────────────────────────────────────── */}
              <Show when={currentStep()?.type === "portfolio" && (currentStep()?.fields?.length ?? 0) === 0}>
                <p style={{ "font-size": "13px", color: "#9CA3AF" }}>This step has no fields configured yet.</p>
              </Show>
              <Show when={currentStep()?.type === "portfolio" && (currentStep()?.fields?.length ?? 0) > 0}>
                <div style={{ display: "grid", gap: "10px" }}>
                  <For each={currentStep()?.fields ?? []}>
                    {(field) => (
                      <div>
                        <label style={LABEL}>
                          {field.label}
                          <Show when={field.required}><span style={{ color: "#EF4444" }}> *</span></Show>
                        </label>
                        <textarea
                          rows={3}
                          value={portfolioForm()[field.id] ?? ""}
                          onInput={(e) => setPortfolioField(field.id, e.currentTarget.value)}
                          style={{ ...INPUT, height: "auto", padding: "10px 12px", resize: "vertical" }}
                        />
                      </div>
                    )}
                  </For>
                </div>
              </Show>

              {/* ── review ────────────────────────────────────────────── */}
              <Show when={currentStep()?.type === "review"}>
                <div style={{ padding: "16px", background: "#F9FAFB", "border-radius": "8px" }}>
                  <For each={steps().filter((s) => s.type !== "review")}>
                    {(step) => (
                      <div style={{ "margin-bottom": "12px" }}>
                        <p style={{ margin: "0 0 4px", "font-size": "12px", "font-weight": "700", color: "#111827" }}>{step.title}</p>
                        <For each={step.fields}>
                          {(field) => {
                            const value = step.type === "documents"
                              ? (docUrls()[field.id]
                                  ? (reusedDocs().has(field.id) ? "Reused from existing profile" : "Uploaded")
                                  : "—")
                              : step.type === "portfolio"
                                ? (portfolioForm()[field.id] || "—")
                                : (form()[field.id] || "—");
                            return (
                              <p style={{ margin: "2px 0", "font-size": "12px", color: "#374151" }}>
                                <strong>{field.label}:</strong> {value}
                              </p>
                            );
                          }}
                        </For>
                      </div>
                    )}
                  </For>
                </div>
              </Show>

              {/* ── nav buttons ───────────────────────────────────────── */}
              <div style={{ display: "flex", "justify-content": "space-between", "margin-top": "24px" }}>
                <button
                  type="button"
                  onClick={() => setWizardStep((s) => s - 1)}
                  disabled={wizardStep() === 0}
                  style={{ ...BTN_GHOST, opacity: wizardStep() === 0 ? 0.5 : 1 }}
                >
                  Back
                </button>
                <Show
                  when={wizardStep() < steps().length - 1}
                  fallback={
                    <button type="button" onClick={handleSubmit} disabled={submitting()} style={{ ...BTN_PRIMARY, opacity: submitting() ? 0.7 : 1 }}>
                      {submitting() ? "Submitting..." : "Submit for Verification"}
                    </button>
                  }
                >
                  <button
                    type="button"
                    onClick={() => setWizardStep((s) => s + 1)}
                    disabled={!canAdvance()}
                    style={{ ...BTN_PRIMARY, opacity: canAdvance() ? 1 : 0.5 }}
                  >
                    Next
                  </button>
                </Show>
              </div>

              <Show when={submitMsg()}>
                <div style={{ "margin-top": "12px", padding: "10px 14px", background: "#FEF2F2", border: "1px solid #FECACA", color: "#B91C1C", "font-size": "13px", "font-weight": "600", "border-radius": "6px" }}>
                  {submitMsg()}
                </div>
              </Show>
            </div>
          </Show>
        </div>
      </Show>
    </Show>
  );
}
