import { SEEDED_ONBOARDING_SCHEMAS } from '~/lib/runtime/seed';
import type { OnboardingSubmission, RuntimeOnboardingConfig } from '~/lib/runtime/types';

const FRONTEND_KEY = 'nxtgauge_frontend_runtime_v1';
const ADMIN_BUILDER_KEY = 'nxtgauge_admin_runtime_builder_v1';
const SUBMISSION_KEY = 'nxtgauge_frontend_onboarding_submissions_v1';

type FrontendStore = {
  onboarding: Record<string, RuntimeOnboardingConfig>;
};

function emptyStore(): FrontendStore {
  return { onboarding: {} };
}

function readFrontendStore(): FrontendStore {
  if (typeof window === 'undefined') return emptyStore();
  const raw = window.localStorage.getItem(FRONTEND_KEY);
  if (!raw) return emptyStore();
  try {
    const parsed = JSON.parse(raw) as Partial<FrontendStore>;
    return { onboarding: parsed.onboarding || {} };
  } catch {
    return emptyStore();
  }
}

function writeFrontendStore(store: FrontendStore) {
  if (typeof window === 'undefined') return;
  window.localStorage.setItem(FRONTEND_KEY, JSON.stringify(store));
}

export function ensureSeededRuntimeConfig() {
  const store = readFrontendStore();
  if (Object.keys(store.onboarding).length > 0) return;
  const seeded: Record<string, RuntimeOnboardingConfig> = {};
  SEEDED_ONBOARDING_SCHEMAS.forEach((schema) => {
    seeded[schema.schemaId] = schema;
  });
  writeFrontendStore({ onboarding: seeded });
}

function readAdminBuilderPublishedSchemas(): RuntimeOnboardingConfig[] {
  if (typeof window === 'undefined') return [];
  const raw = window.localStorage.getItem(ADMIN_BUILDER_KEY);
  if (!raw) return [];

  try {
    const parsed = JSON.parse(raw) as { onboarding?: Record<string, { status?: string; payload?: RuntimeOnboardingConfig }> };
    const bucket = parsed.onboarding || {};
    return Object.values(bucket)
      .filter((item) => item?.status === 'published' && item.payload)
      .map((item) => item.payload as RuntimeOnboardingConfig);
  } catch {
    return [];
  }
}

export function getRuntimeOnboardingSchema(input: { schemaId?: string; roleKey?: string }): RuntimeOnboardingConfig | null {
  const adminPublished = readAdminBuilderPublishedSchemas();

  if (input.schemaId) {
    const bySchemaId = adminPublished.find((schema) => schema.schemaId === input.schemaId);
    if (bySchemaId) return bySchemaId;
  }

  if (input.roleKey) {
    const byRole = adminPublished.find((schema) => schema.roleKey.toUpperCase() === input.roleKey?.toUpperCase());
    if (byRole) return byRole;
  }

  const frontendStore = readFrontendStore();
  if (input.schemaId && frontendStore.onboarding[input.schemaId]) {
    return frontendStore.onboarding[input.schemaId];
  }

  if (input.roleKey) {
    const roleKey = input.roleKey.toUpperCase();
    const match = Object.values(frontendStore.onboarding).find((schema) => schema.roleKey.toUpperCase() === roleKey);
    if (match) return match;
  }

  return null;
}

/**
 * Fetches a role's active verification-wizard schema from the backend
 * (GET /api/config/onboarding/by-key/{roleKey}, public, admin-authored via
 * the Onboarding Schema Editor). Falls back to the localStorage-based
 * getRuntimeOnboardingSchema() only if the request fails, so the wizard can
 * still render something during a transient network error.
 */
export async function fetchOnboardingSchemaForRole(roleKey: string): Promise<RuntimeOnboardingConfig | null> {
  try {
    const res = await fetch(`/api/config/onboarding/by-key/${encodeURIComponent(roleKey.toUpperCase())}`, {
      headers: { Accept: 'application/json' },
      credentials: 'include',
    });
    if (!res.ok) return getRuntimeOnboardingSchema({ roleKey });
    const data = await res.json();
    const schemaJson = data?.schema_json;
    if (!schemaJson || !Array.isArray(schemaJson.steps)) return getRuntimeOnboardingSchema({ roleKey });
    return {
      schemaId: String(data?.id ?? `${roleKey}_v${data?.version ?? 1}`),
      roleKey: roleKey.toUpperCase(),
      version: typeof data?.version === 'number' ? data.version : 1,
      steps: schemaJson.steps,
      portfolioModel: schemaJson.portfolioModel,
      enableWizardFlow: Boolean(schemaJson.enableWizardFlow),
    };
  } catch {
    return getRuntimeOnboardingSchema({ roleKey });
  }
}

export function saveOnboardingSubmission(payload: Omit<OnboardingSubmission, 'id' | 'submittedAt'>): OnboardingSubmission {
  const next: OnboardingSubmission = {
    id: crypto.randomUUID(),
    submittedAt: new Date().toISOString(),
    ...payload,
  };

  if (typeof window === 'undefined') return next;

  const raw = window.localStorage.getItem(SUBMISSION_KEY);
  const current = raw ? (JSON.parse(raw) as OnboardingSubmission[]) : [];
  current.unshift(next);
  window.localStorage.setItem(SUBMISSION_KEY, JSON.stringify(current));
  return next;
}
