import type { Transaction } from 'sequelize';
import db from '@/db/models';
import {
  PER_TENANT_CONTENT_TYPES,
  SCHOOL_SCOPED_CONTENT_TYPES,
  ORG_SCOPED_CONTENT_TYPES,
} from '@/shared/constants/content-catalog';
import { CONTENT_CATALOG_DEFAULT_ROWS } from '@/db/seeders/content-catalog-data/content-catalog-seed-payloads';

export type TenantSeedLevel = 'organization' | 'school' | 'campus';

export interface TenantSeedContext {
  level: TenantSeedLevel;
  organizationId: string;
  schoolId?: string | null;
  campusId?: string | null;
}

interface OwnerStamp {
  organizationId: string | null;
  schoolId: string | null;
  campusId: string | null;
}

/**
 * The owning-tenant ids a content type takes when the given tenant level is
 * created — or `null` if this type is not preset at this level. Per-tenant
 * safety quiz exists at org/school/campus; dashboard + parent templates only at
 * org/school/campus; org-scoped only at org; school-scoped only at school; truly
 * global types are seeded once (with no tenant) when the first org is created.
 */
function stampForLevel(
  contentType: string,
  ctx: TenantSeedContext,
): OwnerStamp | null {
  const org = ctx.organizationId;

  if (ORG_SCOPED_CONTENT_TYPES.has(contentType)) {
    return ctx.level === 'organization'
      ? { organizationId: org, schoolId: null, campusId: null }
      : null;
  }

  if (SCHOOL_SCOPED_CONTENT_TYPES.has(contentType)) {
    return ctx.level === 'school' && ctx.schoolId
      ? { organizationId: org, schoolId: ctx.schoolId, campusId: null }
      : null;
  }

  if (PER_TENANT_CONTENT_TYPES.has(contentType)) {
    if (ctx.level === 'organization') {
      return { organizationId: org, schoolId: null, campusId: null };
    }
    if (ctx.level === 'school') {
      return ctx.schoolId
        ? { organizationId: org, schoolId: ctx.schoolId, campusId: null }
        : null;
    }
    return ctx.campusId
      ? { organizationId: org, schoolId: null, campusId: ctx.campusId }
      : null;
  }

  // Truly global/shared content: seeded once (no tenant) at org creation.
  return ctx.level === 'organization'
    ? { organizationId: null, schoolId: null, campusId: null }
    : null;
}

/**
 * Copies the default content a newly-created tenant owns into `content_catalog`,
 * once (idempotent — skips rows that already exist for that tenant). Called from
 * the org/school/campus creation flows so new tenants start with editable
 * defaults from the single defaults source.
 */
export async function seedDefaultContentForTenant(
  ctx: TenantSeedContext,
  transaction?: Transaction,
): Promise<void> {
  for (const row of CONTENT_CATALOG_DEFAULT_ROWS) {
    const stamp = stampForLevel(row.content_type, ctx);
    if (!stamp) {
      continue;
    }
    const where = {
      content_type: row.content_type,
      organizationId: stamp.organizationId,
      schoolId: stamp.schoolId,
      campusId: stamp.campusId,
      classId: null,
    };
    const existing = await db.content_catalog.findOne({
      where,
      paranoid: false,
      transaction,
    });
    if (existing) {
      continue;
    }
    await db.content_catalog.create(
      {
        content_type: row.content_type,
        payload: row.payload,
        active: true,
        importHash: null,
        ...stamp,
        classId: null,
      },
      { transaction },
    );
  }
}
