import { For, Show, createEffect, createResource, createSignal } from 'solid-js';

const API = '';

type FieldType = 'text' | 'textarea' | 'select' | 'number' | 'email' | 'tel' | 'url' | 'date' | 'file';
type StepType = 'basic' | 'documents' | 'portfolio' | 'review';
type PortfolioModel = 'none' | 'custom_data' | 'professional';

type SchemaField = {
  id: string;
  label: string;
  type: FieldType;
  required: boolean;
  lockAfterApproval: boolean;
  options?: string; // comma-separated, editable as plain text; only meaningful for type "select"
};

type SchemaStep = {
  id: string;
  title: string;
  type: StepType;
  fields: SchemaField[];
};

type Role = { id: string; key: string; name: string };

function authHeaders() {
  const token = typeof sessionStorage !== 'undefined' ? sessionStorage.getItem('nxtgauge_admin_access_token') || '' : '';
  return { Accept: 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) };
}

async function fetchRoles(): Promise<Role[]> {
  const res = await fetch(`${API}/api/admin/roles?audience=EXTERNAL`, { headers: authHeaders() });
  if (!res.ok) return [];
  const data = await res.json().catch(() => []);
  const rows = Array.isArray(data) ? data : (data.roles || []);
  return rows.map((r: any) => ({ id: String(r.id), key: String(r.key), name: String(r.name || r.key) }));
}

function emptyField(): SchemaField {
  return { id: '', label: '', type: 'text', required: false, lockAfterApproval: false };
}

function emptyStep(type: StepType): SchemaStep {
  const id = `${type}_${Math.random().toString(36).slice(2, 8)}`;
  const titles: Record<StepType, string> = {
    basic: 'Basic Information',
    documents: 'Documents',
    portfolio: 'My Portfolio',
    review: 'Review and Submit',
  };
  return { id, title: titles[type], type, fields: [] };
}

function parseSchema(schema_json: any): { portfolioModel: PortfolioModel; enableWizardFlow: boolean; steps: SchemaStep[] } {
  const steps: SchemaStep[] = Array.isArray(schema_json?.steps)
    ? schema_json.steps.map((s: any) => ({
        id: String(s.id || `step_${Math.random().toString(36).slice(2, 8)}`),
        title: String(s.title || ''),
        type: (['basic', 'documents', 'portfolio', 'review'].includes(s.type) ? s.type : 'basic') as StepType,
        fields: Array.isArray(s.fields)
          ? s.fields.map((f: any) => ({
              id: String(f.id || ''),
              label: String(f.label || ''),
              type: (f.type || 'text') as FieldType,
              required: Boolean(f.required),
              lockAfterApproval: Boolean(f.lockAfterApproval),
              options: Array.isArray(f.options)
                ? f.options.map((o: any) => (typeof o === 'string' ? o : o?.label ?? o?.value ?? '')).join(', ')
                : '',
            }))
          : [],
      }))
    : [];
  return {
    portfolioModel: (['none', 'custom_data', 'professional'].includes(schema_json?.portfolioModel) ? schema_json.portfolioModel : 'none') as PortfolioModel,
    enableWizardFlow: Boolean(schema_json?.enableWizardFlow),
    steps,
  };
}

function serializeSchema(portfolioModel: PortfolioModel, enableWizardFlow: boolean, steps: SchemaStep[]) {
  return {
    portfolioModel,
    enableWizardFlow,
    steps: steps.map((s) => ({
      id: s.id,
      title: s.title,
      type: s.type,
      fields: s.fields.map((f) => ({
        id: f.id,
        label: f.label,
        type: f.type,
        required: f.required,
        ...(f.lockAfterApproval ? { lockAfterApproval: true } : {}),
        ...(f.type === 'select' && f.options?.trim()
          ? { options: f.options.split(',').map((o) => o.trim()).filter(Boolean).map((o) => ({ label: o, value: o })) }
          : {}),
      })),
    })),
  };
}

export default function OnboardingSchemaEditor() {
  const [roles] = createResource(fetchRoles);
  const [roleId, setRoleId] = createSignal('');
  const [loadedVersion, setLoadedVersion] = createSignal<number | null>(null);
  const [portfolioModel, setPortfolioModel] = createSignal<PortfolioModel>('none');
  const [enableWizardFlow, setEnableWizardFlow] = createSignal(false);
  const [steps, setSteps] = createSignal<SchemaStep[]>([]);
  const [expandedStep, setExpandedStep] = createSignal<string | null>(null);
  const [dragStepId, setDragStepId] = createSignal<string | null>(null);
  const [dragField, setDragField] = createSignal<{ stepId: string; fieldIdx: number } | null>(null);
  const [saving, setSaving] = createSignal(false);
  const [message, setMessage] = createSignal('');
  const [loading, setLoading] = createSignal(false);

  const loadSchemaForRole = async (id: string) => {
    if (!id) return;
    setLoading(true);
    setMessage('');
    try {
      const res = await fetch(`${API}/api/admin/onboarding-config/${id}`, { headers: authHeaders() });
      if (res.ok) {
        const data = await res.json();
        const parsed = parseSchema(data.schema_json);
        setPortfolioModel(parsed.portfolioModel);
        setEnableWizardFlow(parsed.enableWizardFlow);
        setSteps(parsed.steps);
        setLoadedVersion(typeof data.version === 'number' ? data.version : null);
      } else {
        // No active schema yet for this role - start from a blank template.
        setPortfolioModel('none');
        setEnableWizardFlow(false);
        setSteps([emptyStep('basic'), emptyStep('documents'), emptyStep('review')]);
        setLoadedVersion(null);
      }
    } finally {
      setLoading(false);
    }
  };

  createEffect(() => {
    const id = roleId();
    if (id) void loadSchemaForRole(id);
  });

  const addStep = (type: StepType) => setSteps((prev) => [...prev, emptyStep(type)]);
  const removeStep = (id: string) => setSteps((prev) => prev.filter((s) => s.id !== id));
  const updateStep = (id: string, patch: Partial<SchemaStep>) =>
    setSteps((prev) => prev.map((s) => (s.id === id ? { ...s, ...patch } : s)));
  const moveStep = (movingId: string, targetId: string) => {
    if (!movingId || !targetId || movingId === targetId) return;
    setSteps((prev) => {
      const from = prev.findIndex((s) => s.id === movingId);
      const to = prev.findIndex((s) => s.id === targetId);
      if (from === -1 || to === -1) return prev;
      const next = [...prev];
      const [item] = next.splice(from, 1);
      next.splice(to, 0, item);
      return next;
    });
  };

  const addField = (stepId: string) =>
    setSteps((prev) => prev.map((s) => (s.id === stepId ? { ...s, fields: [...s.fields, emptyField()] } : s)));
  const removeField = (stepId: string, idx: number) =>
    setSteps((prev) => prev.map((s) => (s.id === stepId ? { ...s, fields: s.fields.filter((_, i) => i !== idx) } : s)));
  const updateField = (stepId: string, idx: number, patch: Partial<SchemaField>) =>
    setSteps((prev) =>
      prev.map((s) =>
        s.id === stepId ? { ...s, fields: s.fields.map((f, i) => (i === idx ? { ...f, ...patch } : f)) } : s
      )
    );
  const moveField = (stepId: string, from: number, to: number) => {
    if (from === to) return;
    setSteps((prev) =>
      prev.map((s) => {
        if (s.id !== stepId) return s;
        const next = [...s.fields];
        const [item] = next.splice(from, 1);
        next.splice(to, 0, item);
        return { ...s, fields: next };
      })
    );
  };

  // Mirrors the backend check in create_onboarding_config — catches it before
  // the round trip so an admin can't accidentally publish a wizard with
  // nothing to fill in (checkbox on, but a step never got any fields added).
  const validationError = (): string | null => {
    if (!enableWizardFlow()) return null;
    if (steps().length === 0) return 'Cannot enable the wizard flow with no steps configured.';
    const emptyStep = steps().find((s) => s.type !== 'review' && s.fields.length === 0);
    if (emptyStep) return `Cannot enable the wizard flow: step "${emptyStep.title || '(untitled step)'}" has no fields.`;
    return null;
  };

  const handleSave = async () => {
    const id = roleId();
    if (!id) return;
    const error = validationError();
    if (error) {
      setMessage(error);
      return;
    }
    setSaving(true);
    setMessage('');
    try {
      const schema_json = serializeSchema(portfolioModel(), enableWizardFlow(), steps());
      const res = await fetch(`${API}/api/admin/onboarding-config`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...authHeaders() },
        body: JSON.stringify({ role_id: id, schema_json }),
      });
      if (!res.ok) {
        const body = await res.json().catch(() => ({}));
        throw new Error(body?.error || `Save failed (${res.status})`);
      }
      const saved = await res.json();
      setLoadedVersion(typeof saved.version === 'number' ? saved.version : null);
      setMessage('Saved — this is now the active schema for this role.');
    } catch (e: any) {
      setMessage(e?.message || 'Save failed.');
    } finally {
      setSaving(false);
    }
  };

  const FIELD_TYPES: FieldType[] = ['text', 'textarea', 'select', 'number', 'email', 'tel', 'url', 'date', 'file'];
  const STEP_TYPES: StepType[] = ['basic', 'documents', 'portfolio', 'review'];

  return (
    <div class="w-full space-y-4">
      <div>
        <h1 class="text-[28px] font-bold leading-tight text-[#111827]">Onboarding Schema Editor</h1>
        <p class="mt-1 text-[14px] text-[#6B7280]">
          Defines the verification wizard's steps and fields per role — which fields are required, and which
          become permanently locked once the profile is approved. This replaces per-role hardcoding in the
          frontend.
        </p>
      </div>

      <div style="border-radius:12px;border:1px solid #E5E7EB;background:white;padding:16px;display:flex;gap:16px;align-items:flex-end;flex-wrap:wrap">
        <label style="display:flex;flex-direction:column;gap:4px;min-width:240px">
          <span style="font-size:11px;font-weight:800;color:#6B7280;text-transform:uppercase">Role</span>
          <select
            value={roleId()}
            onChange={(e) => setRoleId(e.currentTarget.value)}
            style="height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
          >
            <option value="">Select a role...</option>
            <For each={roles() || []}>{(r) => <option value={r.id}>{r.name} ({r.key})</option>}</For>
          </select>
        </label>

        <Show when={roleId()}>
          <label style="display:flex;flex-direction:column;gap:4px">
            <span style="font-size:11px;font-weight:800;color:#6B7280;text-transform:uppercase">Portfolio Model</span>
            <select
              value={portfolioModel()}
              onChange={(e) => setPortfolioModel(e.currentTarget.value as PortfolioModel)}
              style="height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
            >
              <option value="none">None (no portfolio step)</option>
              <option value="custom_data">Custom data (job-seeker style)</option>
              <option value="professional">Professional (flat fields + showcase items)</option>
            </select>
          </label>

          <label style="display:flex;align-items:center;gap:8px;height:36px;font-size:13px;color:#374151">
            <input type="checkbox" checked={enableWizardFlow()} onChange={(e) => setEnableWizardFlow(e.currentTarget.checked)} />
            Enable verification wizard flow for this role
          </label>

          <button
            type="button"
            disabled={saving() || loading() || !!validationError()}
            onClick={handleSave}
            title={validationError() || undefined}
            style={`height:36px;border-radius:8px;border:none;background:#0D0D2A;color:white;padding:0 16px;font-size:13px;font-weight:700;cursor:pointer;opacity:${saving() || loading() || validationError() ? 0.6 : 1}`}
          >
            {saving() ? 'Saving...' : 'Save Schema'}
          </button>

          <Show when={loadedVersion() !== null}>
            <span style="font-size:12px;color:#6B7280">Current version: {loadedVersion()}</span>
          </Show>
        </Show>
      </div>

      <Show when={message()}>
        <div style="border-radius:10px;border:1px solid #E5E7EB;background:#F9FAFB;padding:10px 14px;font-size:13px;color:#374151">
          {message()}
        </div>
      </Show>

      <Show when={roleId() && !loading()}>
        <div style="display:flex;flex-direction:column;gap:12px">
          <For each={steps()}>
            {(step) => (
              <div
                draggable
                onDragStart={() => setDragStepId(step.id)}
                onDragOver={(e) => e.preventDefault()}
                onDrop={(e) => {
                  e.preventDefault();
                  moveStep(dragStepId() || '', step.id);
                  setDragStepId(null);
                }}
                style={`border-radius:12px;border:1px solid #E5E7EB;background:${dragStepId() === step.id ? '#FFF7ED' : 'white'};overflow:hidden`}
              >
                <div style="display:flex;align-items:center;gap:10px;padding:12px 16px;cursor:grab;background:#FAFAFA;border-bottom:1px solid #F3F4F6">
                  <span style="font-size:14px;color:#9CA3AF">::</span>
                  <input
                    value={step.title}
                    onInput={(e) => updateStep(step.id, { title: e.currentTarget.value })}
                    style="flex:1;height:32px;border-radius:6px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px;font-weight:700"
                  />
                  <select
                    value={step.type}
                    onChange={(e) => updateStep(step.id, { type: e.currentTarget.value as StepType })}
                    style="height:32px;border-radius:6px;border:1px solid #E5E7EB;padding:0 8px;font-size:12px"
                  >
                    <For each={STEP_TYPES}>{(t) => <option value={t}>{t}</option>}</For>
                  </select>
                  <button
                    type="button"
                    onClick={() => setExpandedStep(expandedStep() === step.id ? null : step.id)}
                    style="height:32px;border-radius:6px;border:1px solid #E5E7EB;background:white;padding:0 10px;font-size:12px;font-weight:700;cursor:pointer"
                  >
                    {expandedStep() === step.id ? 'Collapse' : `${step.fields.length} field(s)`}
                  </button>
                  <button
                    type="button"
                    onClick={() => removeStep(step.id)}
                    style="height:32px;border-radius:6px;border:1px solid #FECACA;background:#FEF2F2;color:#B91C1C;padding:0 10px;font-size:12px;font-weight:700;cursor:pointer"
                  >
                    Remove Step
                  </button>
                </div>

                <Show when={expandedStep() === step.id}>
                  <div style="padding:12px 16px;display:flex;flex-direction:column;gap:8px">
                    <For each={step.fields}>
                      {(field, idx) => (
                        <div
                          draggable
                          onDragStart={() => setDragField({ stepId: step.id, fieldIdx: idx() })}
                          onDragOver={(e) => e.preventDefault()}
                          onDrop={(e) => {
                            e.preventDefault();
                            const from = dragField();
                            if (from && from.stepId === step.id) moveField(step.id, from.fieldIdx, idx());
                            setDragField(null);
                          }}
                          style="display:grid;grid-template-columns:1fr 1fr 110px 70px 90px 1fr 70px;gap:8px;align-items:center;border:1px solid #E5E7EB;border-radius:8px;padding:8px;cursor:grab"
                        >
                          <input
                            placeholder="field id (e.g. first_name)"
                            value={field.id}
                            onInput={(e) => updateField(step.id, idx(), { id: e.currentTarget.value })}
                            style="height:30px;border-radius:6px;border:1px solid #E5E7EB;padding:0 8px;font-size:12px"
                          />
                          <input
                            placeholder="label"
                            value={field.label}
                            onInput={(e) => updateField(step.id, idx(), { label: e.currentTarget.value })}
                            style="height:30px;border-radius:6px;border:1px solid #E5E7EB;padding:0 8px;font-size:12px"
                          />
                          <select
                            value={field.type}
                            onChange={(e) => updateField(step.id, idx(), { type: e.currentTarget.value as FieldType })}
                            style="height:30px;border-radius:6px;border:1px solid #E5E7EB;font-size:12px"
                          >
                            <For each={FIELD_TYPES}>{(t) => <option value={t}>{t}</option>}</For>
                          </select>
                          <label style="display:flex;align-items:center;gap:4px;font-size:11px;color:#374151">
                            <input
                              type="checkbox"
                              checked={field.required}
                              onChange={(e) => updateField(step.id, idx(), { required: e.currentTarget.checked })}
                            />
                            Req
                          </label>
                          <label style="display:flex;align-items:center;gap:4px;font-size:11px;color:#B45309">
                            <input
                              type="checkbox"
                              checked={field.lockAfterApproval}
                              onChange={(e) => updateField(step.id, idx(), { lockAfterApproval: e.currentTarget.checked })}
                            />
                            Lock
                          </label>
                          <input
                            placeholder="options (comma-separated, select only)"
                            value={field.options || ''}
                            onInput={(e) => updateField(step.id, idx(), { options: e.currentTarget.value })}
                            style="height:30px;border-radius:6px;border:1px solid #E5E7EB;padding:0 8px;font-size:12px"
                            disabled={field.type !== 'select'}
                          />
                          <button
                            type="button"
                            onClick={() => removeField(step.id, idx())}
                            style="height:30px;border-radius:6px;border:1px solid #FECACA;background:#FEF2F2;color:#B91C1C;font-size:11px;font-weight:700;cursor:pointer"
                          >
                            Remove
                          </button>
                        </div>
                      )}
                    </For>
                    <button
                      type="button"
                      onClick={() => addField(step.id)}
                      style="align-self:flex-start;height:30px;border-radius:6px;border:1px solid #E5E7EB;background:white;padding:0 10px;font-size:12px;font-weight:700;cursor:pointer"
                    >
                      + Add Field
                    </button>
                  </div>
                </Show>
              </div>
            )}
          </For>

          <div style="display:flex;gap:8px;flex-wrap:wrap">
            <For each={STEP_TYPES}>
              {(t) => (
                <button
                  type="button"
                  onClick={() => addStep(t)}
                  style="height:34px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:700;cursor:pointer"
                >
                  + Add {t} step
                </button>
              )}
            </For>
          </div>
        </div>
      </Show>

      <Show when={loading()}>
        <p style="font-size:13px;color:#6B7280">Loading schema...</p>
      </Show>
    </div>
  );
}
