import { v4 as uuid } from 'uuid';
import {
  Op,
  type CreationAttributes,
  type QueryInterface,
} from 'sequelize';
import type { ContentCatalog } from '@/db/models/content_catalog';
import {
  SEED_ORGANIZATION_ID,
  SEED_SCHOOL_ID,
  SEED_SCHOOL_2_ID,
  SEED_SCHOOL_CAMPUS_IDS,
  SEED_ORGANIZATION_2_ID,
  SEED_SECONDARY_SCHOOL_ID,
  SEED_SECONDARY_CAMPUS_ID,
} from '@/shared/constants/seed-fixtures';
import {
  PER_TENANT_CONTENT_TYPES,
  SCHOOL_SCOPED_CONTENT_TYPES,
  ORG_SCOPED_CONTENT_TYPES,
} from '@/shared/constants/content-catalog';
import { CONTENT_CATALOG_SEED_PAYLOADS } from './content-catalog-data/content-catalog-seed-payloads';

/**
 * Owning-tenant ids for a seeded content type, derived from its scope class so
 * scoped users actually see the demo content: per-tenant types are seeded at
 * org, school, and campus levels; school-scoped at schools; org-scoped at orgs;
 * the rest (truly global) carry no tenant.
 */
function seedTenants(contentType: string): Array<{
  organizationId: string | null;
  schoolId: string | null;
  campusId: string | null;
}> {
  const demoCampusIds = [
    ...SEED_SCHOOL_CAMPUS_IDS[SEED_SCHOOL_ID],
    ...SEED_SCHOOL_CAMPUS_IDS[SEED_SCHOOL_2_ID],
  ];

  if (PER_TENANT_CONTENT_TYPES.has(contentType)) {
    return [
      { organizationId: SEED_ORGANIZATION_ID, schoolId: null, campusId: null },
      { organizationId: SEED_ORGANIZATION_ID, schoolId: SEED_SCHOOL_ID, campusId: null },
      { organizationId: SEED_ORGANIZATION_ID, schoolId: SEED_SCHOOL_2_ID, campusId: null },
      ...demoCampusIds.map((campusId) => ({
        organizationId: SEED_ORGANIZATION_ID,
        schoolId: null,
        campusId,
      })),
      { organizationId: SEED_ORGANIZATION_2_ID, schoolId: null, campusId: null },
      { organizationId: SEED_ORGANIZATION_2_ID, schoolId: SEED_SECONDARY_SCHOOL_ID, campusId: null },
      { organizationId: SEED_ORGANIZATION_2_ID, schoolId: null, campusId: SEED_SECONDARY_CAMPUS_ID },
    ];
  }
  if (SCHOOL_SCOPED_CONTENT_TYPES.has(contentType)) {
    return [
      { organizationId: SEED_ORGANIZATION_ID, schoolId: SEED_SCHOOL_ID, campusId: null },
      { organizationId: SEED_ORGANIZATION_ID, schoolId: SEED_SCHOOL_2_ID, campusId: null },
      { organizationId: SEED_ORGANIZATION_2_ID, schoolId: SEED_SECONDARY_SCHOOL_ID, campusId: null },
    ];
  }
  if (ORG_SCOPED_CONTENT_TYPES.has(contentType)) {
    return [
      { organizationId: SEED_ORGANIZATION_ID, schoolId: null, campusId: null },
      { organizationId: SEED_ORGANIZATION_2_ID, schoolId: null, campusId: null },
    ];
  }
  return [{ organizationId: null, schoolId: null, campusId: null }];
}

function tenantImportHash(
  contentType: string,
  stamp: { organizationId: string | null; schoolId: string | null; campusId: string | null },
): string {
  const suffix = stamp.campusId
    ?? stamp.schoolId
    ?? stamp.organizationId
    ?? 'global';

  return `content-catalog-${contentType}-${suffix}`;
}

const CONTENT_CATALOG_SEED_ROWS = Object.freeze([
  { content_type: 'classroom-strategies', payload: CONTENT_CATALOG_SEED_PAYLOADS.classroomStrategies },
  { content_type: 'safety-qbs-quiz', payload: CONTENT_CATALOG_SEED_PAYLOADS.safetyQbsQuiz },
  { content_type: 'sign-language-items', payload: CONTENT_CATALOG_SEED_PAYLOADS.signLanguageItems },
  { content_type: 'sign-language-page-content', payload: CONTENT_CATALOG_SEED_PAYLOADS.signLanguagePageContent },
  { content_type: 'regulation-zones', payload: CONTENT_CATALOG_SEED_PAYLOADS.regulationZones },
  { content_type: 'zones-of-regulation-page-content', payload: CONTENT_CATALOG_SEED_PAYLOADS.zonesOfRegulationPageContent },
  { content_type: 'dashboard-teacher-images', payload: CONTENT_CATALOG_SEED_PAYLOADS.dashboardTeacherImages },
  { content_type: 'dashboard-encouraging-quotes', payload: CONTENT_CATALOG_SEED_PAYLOADS.dashboardEncouragingQuotes },
  { content_type: 'dashboard-compliance-items', payload: CONTENT_CATALOG_SEED_PAYLOADS.dashboardComplianceItems },
  { content_type: 'dashboard-sign-of-week', payload: CONTENT_CATALOG_SEED_PAYLOADS.dashboardSignOfWeek },
  { content_type: 'community-organizations', payload: CONTENT_CATALOG_SEED_PAYLOADS.communityOrganizations },
  { content_type: 'vocational-opportunities', payload: CONTENT_CATALOG_SEED_PAYLOADS.vocationalOpportunities },
  { content_type: 'emotional-intelligence-assessment-questions', payload: CONTENT_CATALOG_SEED_PAYLOADS.emotionalIntelligenceAssessmentQuestions },
  { content_type: 'emotional-intelligence-weekly-topics', payload: CONTENT_CATALOG_SEED_PAYLOADS.emotionalIntelligenceWeeklyTopics },
  { content_type: 'emotional-intelligence-growth-tips', payload: CONTENT_CATALOG_SEED_PAYLOADS.emotionalIntelligenceGrowthTips },
  { content_type: 'emotional-intelligence-team-wellness-metrics', payload: CONTENT_CATALOG_SEED_PAYLOADS.emotionalIntelligenceTeamWellnessMetrics },
  { content_type: 'esa-funding-content', payload: CONTENT_CATALOG_SEED_PAYLOADS.esaFundingContent },
  // `safety-protocols` is no longer served from the content catalog — safety
  // protocols are now seeded into `policy_documents` (see the policy-documents
  // seeder), which the Safety Protocols page reads.
  { content_type: 'emotional-intelligence-weekly-focus', payload: CONTENT_CATALOG_SEED_PAYLOADS.emotionalIntelligenceWeeklyFocus },
]);

export default {
  up: async (queryInterface: QueryInterface) => {
    const now = new Date();
    const contentTypes = CONTENT_CATALOG_SEED_ROWS.map((row) => row.content_type);

    await queryInterface.bulkDelete('content_catalog', {
      content_type: {
        [Op.in]: contentTypes,
      },
    });

    const rows: CreationAttributes<ContentCatalog>[] =
      CONTENT_CATALOG_SEED_ROWS.flatMap((row) => seedTenants(row.content_type).map((stamp) => ({
        id: uuid(),
        content_type: row.content_type,
        // payload is JSONB; bulkInsert needs a serialized value (Postgres casts
        // the JSON text to jsonb on insert).
        payload: JSON.stringify(row.payload),
        active: true,
        importHash: tenantImportHash(row.content_type, stamp),
        ...stamp,
        classId: null,
        createdAt: now,
        updatedAt: now,
      })));

    await queryInterface.bulkInsert('content_catalog', rows);
  },

  down: async (queryInterface: QueryInterface) => {
    await queryInterface.bulkDelete('content_catalog', {
      content_type: {
        [Op.in]: CONTENT_CATALOG_SEED_ROWS.map((row) => row.content_type),
      },
    });
  },
};
