/**
 * Deterministic grid topology generator.
 *
 * Builds a coherent national fleet: generation sized to cover each region's peak with a
 * realistic reserve, transformers sized so their aggregate loading reproduces regional
 * demand, and every asset placed at real-ish coordinates around its region centre.
 *
 * Everything is derived from the region table and a fixed seed, so re-running the seed
 * produces byte-identical topology.
 */

import { REGIONS, type RegionSeed } from '../../src/lib/data/regions'
import { seededInt, seededPick, seededRange, seededUnit } from '../../src/lib/engine/rng'
import { DEMO_ASSET_CODE, DEMO_REGION_CODE } from '../../src/lib/demo/config'

const YEAR_MS = 365.25 * 24 * 3_600_000

export interface SiteSpec {
  code: string
  name: string
  nameAr: string
  regionCode: string
  kind: string
  lat: number
  lon: number
  voltageLevelKv: number
  commissionedAt: Date
}

export interface AssetSpec {
  code: string
  name: string
  nameAr: string
  assetTypeKey: string
  siteCode: string
  regionCode: string
  lat: number
  lon: number
  capacityMw: number
  voltageKv: number
  ratedTempC: number
  coolingType: string
  manufacturer: string
  model: string
  serialNumber: string
  installedAt: Date
  lastMaintenanceAt: Date | null
  nextMaintenanceAt: Date | null
  healthScore: number
  criticality: string
  status: string
  customersServed: number
  seed: number
  profileKey: string
  baselineLoadPct: number
  peakHour: number
  volatility: number
  agingFactor: number
  isFlexibleLoad: boolean
  hasBatterySupport: boolean
}

export const ASSET_TYPES = [
  {
    key: 'power_plant',
    name: 'Power Plant',
    nameAr: 'محطة توليد',
    category: 'generation',
    icon: 'plant',
    expectedLifeYears: 35,
    criticalityWeight: 1.4,
  },
  {
    key: 'substation',
    name: 'Substation',
    nameAr: 'محطة تحويل',
    category: 'network',
    icon: 'substation',
    expectedLifeYears: 40,
    criticalityWeight: 1.3,
  },
  {
    key: 'transformer',
    name: 'Transformer',
    nameAr: 'محول',
    category: 'network',
    icon: 'transformer',
    expectedLifeYears: 30,
    criticalityWeight: 1.2,
  },
  {
    key: 'transmission_line',
    name: 'Transmission Line',
    nameAr: 'خط نقل',
    category: 'network',
    icon: 'line',
    expectedLifeYears: 45,
    criticalityWeight: 1.1,
  },
  {
    key: 'battery_storage',
    name: 'Battery Storage',
    nameAr: 'تخزين بطاريات',
    category: 'storage',
    icon: 'battery',
    expectedLifeYears: 15,
    criticalityWeight: 0.9,
  },
  {
    key: 'solar_farm',
    name: 'Solar Farm',
    nameAr: 'محطة طاقة شمسية',
    category: 'renewable',
    icon: 'solar',
    expectedLifeYears: 25,
    criticalityWeight: 0.8,
  },
  {
    key: 'wind_farm',
    name: 'Wind Farm',
    nameAr: 'محطة طاقة رياح',
    category: 'renewable',
    icon: 'wind',
    expectedLifeYears: 25,
    criticalityWeight: 0.8,
  },
  {
    key: 'industrial_load',
    name: 'Industrial Load',
    nameAr: 'حمل صناعي',
    category: 'load',
    icon: 'industry',
    expectedLifeYears: 30,
    criticalityWeight: 1.0,
  },
  {
    key: 'ev_hub',
    name: 'EV Charging Hub',
    nameAr: 'مركز شحن مركبات كهربائية',
    category: 'load',
    icon: 'ev',
    expectedLifeYears: 12,
    criticalityWeight: 0.7,
  },
] as const

/** Named localities per region, used for site names and coordinates. */
const LOCALITIES: Record<string, Array<{ en: string; ar: string; dLat: number; dLon: number }>> = {
  RYD: [
    { en: 'Al Hair', ar: 'الحائر', dLat: -0.34, dLon: 0.12 },
    { en: 'Salboukh', ar: 'السلبوخ', dLat: 0.38, dLon: -0.24 },
    { en: 'Al Faisaliyah', ar: 'الفيصلية', dLat: 0.04, dLon: 0.02 },
    { en: 'Al Naseem', ar: 'النسيم', dLat: 0.09, dLon: 0.16 },
    { en: 'Diriyah', ar: 'الدرعية', dLat: 0.14, dLon: -0.18 },
    { en: 'Al Rimal', ar: 'الرمال', dLat: 0.12, dLon: 0.29 },
    { en: 'Irqah', ar: 'عرقة', dLat: 0.02, dLon: -0.15 },
    { en: 'Al Malaz', ar: 'الملز', dLat: -0.02, dLon: 0.07 },
    { en: 'Sulaymaniyah', ar: 'السليمانية', dLat: 0.06, dLon: 0.0 },
    { en: 'Al Kharj Road', ar: 'طريق الخرج', dLat: -0.22, dLon: 0.25 },
  ],
  JED: [
    { en: 'Obhur', ar: 'أبحر', dLat: 0.28, dLon: -0.04 },
    { en: 'Al Rehab', ar: 'الرحاب', dLat: 0.05, dLon: 0.05 },
    { en: 'Al Hamra', ar: 'الحمراء', dLat: 0.01, dLon: -0.02 },
    { en: 'Bahrah', ar: 'بحرة', dLat: -0.12, dLon: 0.31 },
    { en: 'Thuwal', ar: 'ثول', dLat: 0.72, dLon: -0.09 },
    { en: 'Al Salamah', ar: 'السلامة', dLat: 0.08, dLon: 0.01 },
    { en: 'Briman', ar: 'بريمان', dLat: 0.13, dLon: 0.09 },
  ],
  DMM: [
    { en: 'Jubail', ar: 'الجبيل', dLat: 0.62, dLon: -0.28 },
    { en: 'Qatif', ar: 'القطيف', dLat: 0.15, dLon: -0.07 },
    { en: 'Al Khobar', ar: 'الخبر', dLat: -0.16, dLon: 0.09 },
    { en: 'Dhahran', ar: 'الظهران', dLat: -0.13, dLon: 0.02 },
    { en: 'Ras Tanura', ar: 'رأس تنورة', dLat: 0.24, dLon: 0.02 },
    { en: 'Abqaiq', ar: 'بقيق', dLat: -0.45, dLon: -0.15 },
    { en: 'Safwa', ar: 'صفوى', dLat: 0.21, dLon: -0.12 },
    { en: 'Sayhat', ar: 'سيهات', dLat: 0.09, dLon: -0.03 },
  ],
  MAK: [
    { en: 'Al Aziziyah', ar: 'العزيزية', dLat: -0.04, dLon: 0.03 },
    { en: 'Al Sharai', ar: 'الشرائع', dLat: 0.08, dLon: 0.12 },
    { en: 'Mina', ar: 'منى', dLat: 0.02, dLon: 0.06 },
    { en: 'Al Kakiyah', ar: 'الككية', dLat: -0.02, dLon: -0.04 },
    { en: 'Al Hijrah', ar: 'الهجرة', dLat: 0.06, dLon: -0.02 },
  ],
  MED: [
    { en: 'Quba', ar: 'قباء', dLat: -0.04, dLon: 0.02 },
    { en: 'Al Aqiq', ar: 'العقيق', dLat: 0.02, dLon: -0.05 },
    { en: 'Al Hijrah', ar: 'الهجرة', dLat: 0.08, dLon: 0.04 },
    { en: 'Badr', ar: 'بدر', dLat: -0.44, dLon: -0.62 },
  ],
  TUU: [
    { en: 'Tabuk North', ar: 'تبوك الشمالية', dLat: 0.11, dLon: 0.03 },
    { en: 'Haql', ar: 'حقل', dLat: 0.86, dLon: -1.68 },
    { en: 'Duba', ar: 'ضبا', dLat: -0.9, dLon: -0.36 },
  ],
  NEO: [
    { en: 'Oxagon', ar: 'أوكساجون', dLat: -0.18, dLon: 0.06 },
    { en: 'Trojena', ar: 'تروجينا', dLat: 0.34, dLon: 0.62 },
    { en: 'Sindalah', ar: 'سندالة', dLat: 0.09, dLon: -0.28 },
  ],
  JAZ: [
    { en: 'Jazan City', ar: 'مدينة جازان', dLat: 0.02, dLon: 0.03 },
    { en: 'Sabya', ar: 'صبيا', dLat: 0.27, dLon: 0.18 },
    { en: 'Abu Arish', ar: 'أبو عريش', dLat: 0.08, dLon: 0.22 },
  ],
  ABT: [
    { en: 'Abha North', ar: 'أبها الشمالية', dLat: 0.09, dLon: 0.02 },
    { en: 'Khamis Mushait', ar: 'خميس مشيط', dLat: 0.06, dLon: 0.23 },
    { en: 'Ahad Rufaidah', ar: 'أحد رفيدة', dLat: -0.06, dLon: 0.14 },
  ],
  QSM: [
    { en: 'Buraydah', ar: 'بريدة', dLat: 0.02, dLon: 0.01 },
    { en: 'Unaizah', ar: 'عنيزة', dLat: -0.24, dLon: 0.03 },
    { en: 'Al Rass', ar: 'الرس', dLat: -0.32, dLon: -0.52 },
    { en: 'Al Bukayriyah', ar: 'البكيرية', dLat: -0.08, dLon: -0.31 },
  ],
}

/** Generation mix per region, as a share of that region's installed capacity. */
const GENERATION_MIX: Record<string, { solar: number; wind: number; battery: number }> = {
  RYD: { solar: 0.16, wind: 0, battery: 0.05 },
  JED: { solar: 0.13, wind: 0, battery: 0.04 },
  DMM: { solar: 0.11, wind: 0, battery: 0.05 },
  MAK: { solar: 0.12, wind: 0, battery: 0.03 },
  MED: { solar: 0.18, wind: 0, battery: 0.04 },
  TUU: { solar: 0.31, wind: 0.14, battery: 0.08 },
  NEO: { solar: 0.28, wind: 0.34, battery: 0.14 },
  JAZ: { solar: 0.14, wind: 0.08, battery: 0.04 },
  ABT: { solar: 0.19, wind: 0.06, battery: 0.04 },
  QSM: { solar: 0.26, wind: 0, battery: 0.05 },
}

const TRANSFORMER_MAKERS = [
  { m: 'Hitachi Energy', models: ['TrafoStar 500', 'TrafoStar 750', 'RESIBLOC 63'] },
  { m: 'Siemens Energy', models: ['GEAFOL 125', 'SITRAS 500', 'TR-380/132'] },
  { m: 'Saudi Transformers Co.', models: ['STC-500B', 'STC-125P', 'STC-63D'] },
  { m: 'Hyundai Electric', models: ['HYT-500', 'HYT-160', 'HYT-63'] },
]

const PLANT_MAKERS = [
  { m: 'GE Vernova', models: ['9HA.02 CCGT', '7F.05 CCGT'] },
  { m: 'Siemens Energy', models: ['SGT5-9000HL', 'SGT6-8000H'] },
  { m: 'Mitsubishi Power', models: ['M701JAC', 'M501GAC'] },
]

function siteCoord(region: RegionSeed, index: number) {
  const list = LOCALITIES[region.code]
  const locality = list[index % list.length]
  const jitterSeed = region.code.charCodeAt(0) * 977 + index * 31
  return {
    locality,
    lat: region.lat + locality.dLat + seededRange(jitterSeed, 1, -0.02, 0.02),
    lon: region.lon + locality.dLon + seededRange(jitterSeed, 2, -0.02, 0.02),
  }
}

function assetCoord(lat: number, lon: number, seed: number, salt: number) {
  return {
    lat: lat + seededRange(seed, salt, -0.012, 0.012),
    lon: lon + seededRange(seed, salt + 1, -0.012, 0.012),
  }
}

/**
 * Stable per-asset seed derived from its code (FNV-1a).
 * Reduced modulo 2^31-1 so it fits a signed 32-bit INT column on both engines.
 */
function codeSeed(code: string): number {
  let h = 2166136261
  for (let i = 0; i < code.length; i += 1) {
    h ^= code.charCodeAt(i)
    h = Math.imul(h, 16777619)
  }
  return (h >>> 0) % 2147483647
}

export interface Topology {
  sites: SiteSpec[]
  assets: AssetSpec[]
}

/**
 * Number of bulk transformers a region needs. Sized around a 520 MVA average, which is
 * what a 380/132 kV bulk supply point actually looks like in this grid.
 */
function transformerCountFor(region: RegionSeed): number {
  const loadCapacity = region.peakDemandMw / 0.85
  return Math.max(4, Math.round((loadCapacity * 0.86) / 520))
}

export function buildTopology(now: number): Topology {
  const sites: SiteSpec[] = []
  const assets: AssetSpec[] = []

  let transformerCounter = 100
  let lineCounter = 200
  let plantCounter = 300
  let solarCounter = 400
  let windCounter = 450
  let batteryCounter = 500
  let industrialCounter = 600
  let evCounter = 700

  for (const region of REGIONS) {
    const rSeed = codeSeed(region.code)
    const loadCapacity = region.peakDemandMw / 0.85
    const transformerCapacityTotal = loadCapacity * 0.86
    const industrialCapacityTotal = loadCapacity * 0.09
    const evCapacityTotal = loadCapacity * 0.05

    const nTransformers = transformerCountFor(region)
    const nSubstations = Math.max(2, Math.ceil(nTransformers / 3.5))
    const mix = GENERATION_MIX[region.code]

    // ── Substations ─────────────────────────────────────────────────────────
    const substationSites: SiteSpec[] = []
    for (let s = 0; s < nSubstations; s += 1) {
      const { locality, lat, lon } = siteCoord(region, s)
      const site: SiteSpec = {
        code: `SS-${region.code}-${String(s + 1).padStart(2, '0')}`,
        name: `${locality.en} Substation`,
        nameAr: `محطة تحويل ${locality.ar}`,
        regionCode: region.code,
        kind: 'substation',
        lat,
        lon,
        voltageLevelKv: s % 3 === 2 ? 132 : 380,
        commissionedAt: new Date(now - seededRange(rSeed, s + 10, 6, 32) * YEAR_MS),
      }
      sites.push(site)
      substationSites.push(site)

      assets.push({
        code: `SUB-${region.code}-${String(s + 1).padStart(2, '0')}`,
        name: `${locality.en} Substation`,
        nameAr: `محطة تحويل ${locality.ar}`,
        assetTypeKey: 'substation',
        siteCode: site.code,
        regionCode: region.code,
        lat,
        lon,
        capacityMw: Math.round(transformerCapacityTotal / nSubstations),
        voltageKv: site.voltageLevelKv,
        ratedTempC: 90,
        coolingType: 'ONAF',
        manufacturer: 'Saudi Electricity Company',
        model: `BSP-${site.voltageLevelKv}`,
        serialNumber: `SN-SUB-${region.code}-${s + 1}`,
        installedAt: site.commissionedAt,
        lastMaintenanceAt: new Date(now - seededRange(rSeed, s + 40, 30, 400) * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(rSeed, s + 41, 20, 240) * 86_400_000),
        healthScore: Math.round(seededRange(rSeed, s + 50, 72, 96)),
        criticality: s === 0 ? 'critical' : 'high',
        status: 'online',
        customersServed: Math.round((region.populationK * 1000 * 0.42) / nSubstations),
        seed: codeSeed(`SUB-${region.code}-${s}`),
        profileKey: 'urban',
        baselineLoadPct: seededRange(rSeed, s + 60, 55, 70),
        peakHour: 15,
        volatility: 0.04,
        agingFactor: 1,
        isFlexibleLoad: false,
        hasBatterySupport: mix.battery > 0,
      })
    }

    // ── Transformers ────────────────────────────────────────────────────────
    // A handful of primary distribution units (132/13.8 kV, 63–125 MVA) sit alongside
    // the bulk 380/132 kV fleet; the demo asset T-108 is one of them.
    const primaryCount = region.code === DEMO_REGION_CODE ? 3 : nTransformers >= 8 ? 2 : 1
    const primaryCapacities: number[] = []
    for (let i = 0; i < primaryCount; i += 1) {
      primaryCapacities.push(i === 0 && region.code === DEMO_REGION_CODE ? 63 : [63, 80, 125][i % 3])
    }
    const primaryTotal = primaryCapacities.reduce((a, b) => a + b, 0)
    const bulkCount = Math.max(1, nTransformers - primaryCount)
    const bulkAverage = (transformerCapacityTotal - primaryTotal) / bulkCount

    for (let t = 0; t < nTransformers; t += 1) {
      const isPrimary = t < primaryCount
      const isDemoAsset = region.code === DEMO_REGION_CODE && t === 0
      transformerCounter += 1
      // The demo asset claims a fixed code, so skip that number in the sequence rather
      // than letting the counter hand it out a second time.
      if (!isDemoAsset && `T-${transformerCounter}` === DEMO_ASSET_CODE) transformerCounter += 1
      const code = isDemoAsset ? DEMO_ASSET_CODE : `T-${transformerCounter}`
      const seed = codeSeed(code)
      const site = substationSites[t % substationSites.length]
      const { lat, lon } = assetCoord(site.lat, site.lon, seed, 1)
      const maker = seededPick(seed, 3, TRANSFORMER_MAKERS)

      const capacityMw = isPrimary
        ? primaryCapacities[t]
        : Math.round(bulkAverage * seededRange(seed, 4, 0.78, 1.22))

      // A deliberately mixed condition profile: most of the fleet is healthy, a minority
      // is ageing, so the platform always has something meaningful to say.
      const conditionRoll = seededUnit(seed, 7)
      const ageYears = isDemoAsset ? 23.3 : seededRange(seed, 8, 2, 31)
      const health = isDemoAsset
        ? 54
        : conditionRoll < 0.1
          ? Math.round(seededRange(seed, 9, 42, 60))
          : conditionRoll < 0.3
            ? Math.round(seededRange(seed, 9, 60, 76))
            : Math.round(seededRange(seed, 9, 76, 97))

      const baselineLoad = isDemoAsset
        ? 68
        : conditionRoll < 0.12
          ? seededRange(seed, 11, 72, 84)
          : seededRange(seed, 11, 48, 72)

      const lastMaintDays = isDemoAsset ? 560 : seededRange(seed, 12, 20, 620)

      assets.push({
        code,
        name: isPrimary
          ? `${site.name.replace(' Substation', '')} Primary Transformer ${t + 1}`
          : `${site.name.replace(' Substation', '')} Bulk Transformer ${t + 1}`,
        nameAr: isPrimary
          ? `محول توزيع رئيسي ${t + 1} - ${site.nameAr.replace('محطة تحويل ', '')}`
          : `محول نقل ${t + 1} - ${site.nameAr.replace('محطة تحويل ', '')}`,
        assetTypeKey: 'transformer',
        siteCode: site.code,
        regionCode: region.code,
        lat,
        lon,
        capacityMw,
        voltageKv: isPrimary ? 13.8 : 132,
        ratedTempC: 95,
        coolingType: isPrimary ? 'ONAF' : seededPick(seed, 13, ['ONAF', 'OFAF', 'ONAN']),
        manufacturer: maker.m,
        model: seededPick(seed, 14, maker.models),
        serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
        installedAt: new Date(now - ageYears * YEAR_MS),
        lastMaintenanceAt: new Date(now - lastMaintDays * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(seed, 15, -30, 260) * 86_400_000),
        healthScore: health,
        criticality: isDemoAsset
          ? 'critical'
          : health < 62
            ? 'critical'
            : health < 78
              ? 'high'
              : capacityMw > 400
                ? 'high'
                : 'medium',
        status: 'online',
        customersServed: isDemoAsset
          ? 148_000
          : Math.round(capacityMw * seededRange(seed, 16, 180, 340)),
        seed,
        profileKey: isPrimary ? 'urban' : seededPick(seed, 17, ['urban', 'residential', 'commercial']),
        baselineLoadPct: baselineLoad,
        peakHour: isDemoAsset ? 15 : seededInt(seed, 18, 13, 17),
        volatility: isDemoAsset ? 0.05 : seededRange(seed, 19, 0.03, 0.07),
        agingFactor: isDemoAsset ? 1.25 : 0.9 + (ageYears / 30) * 0.45,
        isFlexibleLoad: false,
        hasBatterySupport: mix.battery > 0,
      })
    }

    // ── Transmission lines ──────────────────────────────────────────────────
    const nLines = region.peakDemandMw > 9000 ? 3 : 2
    for (let l = 0; l < nLines; l += 1) {
      lineCounter += 1
      const code = `TL-${lineCounter}`
      const seed = codeSeed(code)
      const from = substationSites[l % substationSites.length]
      const to = substationSites[(l + 1) % substationSites.length]
      assets.push({
        code,
        name: `${from.name.replace(' Substation', '')} – ${to.name.replace(' Substation', '')} 380 kV Line`,
        nameAr: `خط نقل ٣٨٠ ك.ف ${from.nameAr.replace('محطة تحويل ', '')} – ${to.nameAr.replace('محطة تحويل ', '')}`,
        assetTypeKey: 'transmission_line',
        siteCode: from.code,
        regionCode: region.code,
        lat: (from.lat + to.lat) / 2,
        lon: (from.lon + to.lon) / 2,
        capacityMw: Math.round(seededRange(seed, 2, 900, 2400)),
        voltageKv: 380,
        ratedTempC: 80,
        coolingType: 'NONE',
        manufacturer: 'Saudi Cable Company',
        model: seededPick(seed, 3, ['ACSR Bersimis', 'ACCC Drake', 'AAAC Zebra']),
        serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
        installedAt: new Date(now - seededRange(seed, 4, 4, 30) * YEAR_MS),
        lastMaintenanceAt: new Date(now - seededRange(seed, 5, 40, 500) * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(seed, 6, 30, 300) * 86_400_000),
        healthScore: Math.round(seededRange(seed, 7, 68, 96)),
        criticality: 'high',
        status: 'online',
        customersServed: 0,
        seed,
        profileKey: 'transmission',
        baselineLoadPct: seededRange(seed, 8, 42, 68),
        peakHour: 15,
        volatility: 0.05,
        agingFactor: 1,
        isFlexibleLoad: false,
        hasBatterySupport: false,
      })
    }

    // ── Generation ──────────────────────────────────────────────────────────
    const solarCapacity = region.capacityMw * mix.solar
    const windCapacity = region.capacityMw * mix.wind
    const batteryCapacity = region.capacityMw * mix.battery
    const plantCapacity = region.capacityMw - solarCapacity - windCapacity - batteryCapacity

    const nPlants = region.capacityMw > 12000 ? 3 : region.capacityMw > 5000 ? 2 : 1
    for (let g = 0; g < nPlants; g += 1) {
      plantCounter += 1
      const code = `PP-${plantCounter}`
      const seed = codeSeed(code)
      const { locality, lat, lon } = siteCoord(region, g + 1)
      const site: SiteSpec = {
        code: `PL-${region.code}-${g + 1}`,
        name: `${locality.en} Power Plant`,
        nameAr: `محطة توليد ${locality.ar}`,
        regionCode: region.code,
        kind: 'power_plant',
        lat,
        lon,
        voltageLevelKv: 380,
        commissionedAt: new Date(now - seededRange(seed, 1, 5, 26) * YEAR_MS),
      }
      sites.push(site)
      const maker = seededPick(seed, 2, PLANT_MAKERS)
      assets.push({
        code,
        name: `${locality.en} Combined Cycle Plant ${g + 1}`,
        nameAr: `محطة ${locality.ar} للدورة المركبة ${g + 1}`,
        assetTypeKey: 'power_plant',
        siteCode: site.code,
        regionCode: region.code,
        lat,
        lon,
        capacityMw: Math.round(plantCapacity / nPlants),
        voltageKv: 380,
        ratedTempC: 110,
        coolingType: 'OFWF',
        manufacturer: maker.m,
        model: seededPick(seed, 3, maker.models),
        serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
        installedAt: site.commissionedAt,
        lastMaintenanceAt: new Date(now - seededRange(seed, 4, 20, 380) * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(seed, 5, 30, 300) * 86_400_000),
        healthScore: Math.round(seededRange(seed, 6, 74, 97)),
        criticality: 'critical',
        status: 'online',
        customersServed: 0,
        seed,
        profileKey: 'generation',
        baselineLoadPct: seededRange(seed, 7, 58, 76),
        peakHour: 15,
        volatility: 0.04,
        agingFactor: 1,
        isFlexibleLoad: false,
        hasBatterySupport: false,
      })
    }

    if (solarCapacity > 50) {
      const nSolar = solarCapacity > 1800 ? 2 : 1
      for (let s = 0; s < nSolar; s += 1) {
        solarCounter += 1
        const code = `SF-${solarCounter}`
        const seed = codeSeed(code)
        const { locality, lat, lon } = siteCoord(region, s + 2)
        const site: SiteSpec = {
          code: `SL-${region.code}-${s + 1}`,
          name: `${locality.en} Solar Park`,
          nameAr: `المجمع الشمسي ${locality.ar}`,
          regionCode: region.code,
          kind: 'solar_farm',
          lat: lat + 0.18,
          lon: lon + 0.2,
          voltageLevelKv: 132,
          commissionedAt: new Date(now - seededRange(seed, 1, 1, 8) * YEAR_MS),
        }
        sites.push(site)
        assets.push({
          code,
          name: `${locality.en} Solar PV ${s + 1}`,
          nameAr: `محطة ${locality.ar} الكهروضوئية ${s + 1}`,
          assetTypeKey: 'solar_farm',
          siteCode: site.code,
          regionCode: region.code,
          lat: site.lat,
          lon: site.lon,
          capacityMw: Math.round(solarCapacity / nSolar),
          voltageKv: 132,
          ratedTempC: 85,
          coolingType: 'NONE',
          manufacturer: seededPick(seed, 2, ['JinkoSolar', 'LONGi', 'First Solar', 'Trina Solar']),
          model: seededPick(seed, 3, ['Tiger Neo 620W', 'Hi-MO 7', 'Series 7 CuRe']),
          serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
          installedAt: site.commissionedAt,
          lastMaintenanceAt: new Date(now - seededRange(seed, 4, 10, 200) * 86_400_000),
          nextMaintenanceAt: new Date(now + seededRange(seed, 5, 20, 200) * 86_400_000),
          healthScore: Math.round(seededRange(seed, 6, 82, 99)),
          criticality: 'medium',
          status: 'online',
          customersServed: 0,
          seed,
          profileKey: 'generation',
          baselineLoadPct: 100,
          peakHour: 12,
          volatility: 0.05,
          agingFactor: 1,
          isFlexibleLoad: false,
          hasBatterySupport: true,
        })
      }
    }

    if (windCapacity > 50) {
      windCounter += 1
      const code = `WF-${windCounter}`
      const seed = codeSeed(code)
      const { locality, lat, lon } = siteCoord(region, 1)
      const site: SiteSpec = {
        code: `WD-${region.code}-1`,
        name: `${locality.en} Wind Farm`,
        nameAr: `محطة رياح ${locality.ar}`,
        regionCode: region.code,
        kind: 'wind_farm',
        lat: lat - 0.22,
        lon: lon + 0.16,
        voltageLevelKv: 132,
        commissionedAt: new Date(now - seededRange(seed, 1, 1, 7) * YEAR_MS),
      }
      sites.push(site)
      assets.push({
        code,
        name: `${locality.en} Wind Farm`,
        nameAr: `محطة رياح ${locality.ar}`,
        assetTypeKey: 'wind_farm',
        siteCode: site.code,
        regionCode: region.code,
        lat: site.lat,
        lon: site.lon,
        capacityMw: Math.round(windCapacity),
        voltageKv: 132,
        ratedTempC: 80,
        coolingType: 'NONE',
        manufacturer: seededPick(seed, 2, ['Vestas', 'Siemens Gamesa', 'GE Vernova']),
        model: seededPick(seed, 3, ['V162-6.2 MW', 'SG 6.6-170', 'Cypress 5.5 MW']),
        serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
        installedAt: site.commissionedAt,
        lastMaintenanceAt: new Date(now - seededRange(seed, 4, 15, 220) * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(seed, 5, 30, 220) * 86_400_000),
        healthScore: Math.round(seededRange(seed, 6, 80, 98)),
        criticality: 'medium',
        status: 'online',
        customersServed: 0,
        seed,
        profileKey: 'generation',
        baselineLoadPct: 100,
        peakHour: 3,
        volatility: 0.08,
        agingFactor: 1,
        isFlexibleLoad: false,
        hasBatterySupport: true,
      })
    }

    if (batteryCapacity > 20) {
      batteryCounter += 1
      const code = `BS-${batteryCounter}`
      const seed = codeSeed(code)
      const site = substationSites[0]
      assets.push({
        code,
        name: `${site.name.replace(' Substation', '')} BESS`,
        nameAr: `نظام تخزين بطاريات ${site.nameAr.replace('محطة تحويل ', '')}`,
        assetTypeKey: 'battery_storage',
        siteCode: site.code,
        regionCode: region.code,
        lat: site.lat + 0.03,
        lon: site.lon + 0.03,
        capacityMw: Math.round(batteryCapacity),
        voltageKv: 132,
        ratedTempC: 45,
        coolingType: 'OFAF',
        manufacturer: seededPick(seed, 2, ['BYD', 'Tesla', 'Sungrow', 'CATL']),
        model: seededPick(seed, 3, ['Megapack 2XL', 'PowerTitan 2.0', 'Cube T28']),
        serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
        installedAt: new Date(now - seededRange(seed, 4, 0.5, 5) * YEAR_MS),
        lastMaintenanceAt: new Date(now - seededRange(seed, 5, 10, 180) * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(seed, 6, 30, 180) * 86_400_000),
        healthScore: Math.round(seededRange(seed, 7, 84, 99)),
        criticality: 'high',
        status: 'online',
        customersServed: 0,
        seed,
        profileKey: 'generation',
        baselineLoadPct: 100,
        peakHour: 19,
        volatility: 0.03,
        agingFactor: 1,
        isFlexibleLoad: false,
        hasBatterySupport: true,
      })
    }

    // ── Large loads ─────────────────────────────────────────────────────────
    const nIndustrial = region.flexibleShare > 0.18 ? 2 : 1
    for (let i = 0; i < nIndustrial; i += 1) {
      industrialCounter += 1
      const code = `IL-${industrialCounter}`
      const seed = codeSeed(code)
      const { locality, lat, lon } = siteCoord(region, i + 3)
      assets.push({
        code,
        name: `${locality.en} Industrial Complex ${i + 1}`,
        nameAr: `المجمع الصناعي ${locality.ar} ${i + 1}`,
        assetTypeKey: 'industrial_load',
        siteCode: substationSites[i % substationSites.length].code,
        regionCode: region.code,
        lat,
        lon,
        capacityMw: Math.round(industrialCapacityTotal / nIndustrial),
        voltageKv: 132,
        ratedTempC: 85,
        coolingType: 'NONE',
        manufacturer: 'Industrial Customer',
        model: 'Bulk Supply Point',
        serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
        installedAt: new Date(now - seededRange(seed, 1, 3, 25) * YEAR_MS),
        lastMaintenanceAt: new Date(now - seededRange(seed, 2, 30, 300) * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(seed, 3, 40, 300) * 86_400_000),
        healthScore: Math.round(seededRange(seed, 4, 76, 96)),
        criticality: 'high',
        status: 'online',
        customersServed: Math.round(seededRange(seed, 5, 20, 90)),
        seed,
        profileKey: 'industrial',
        baselineLoadPct: seededRange(seed, 6, 62, 82),
        peakHour: 12,
        volatility: 0.06,
        agingFactor: 1,
        isFlexibleLoad: true,
        hasBatterySupport: false,
      })
    }

    if (evCapacityTotal > 40) {
      evCounter += 1
      const code = `EV-${evCounter}`
      const seed = codeSeed(code)
      const { locality, lat, lon } = siteCoord(region, 2)
      assets.push({
        code,
        name: `${locality.en} EV Charging Hub`,
        nameAr: `مركز شحن المركبات الكهربائية ${locality.ar}`,
        assetTypeKey: 'ev_hub',
        siteCode: substationSites[0].code,
        regionCode: region.code,
        lat,
        lon,
        capacityMw: Math.round(evCapacityTotal),
        voltageKv: 13.8,
        ratedTempC: 70,
        coolingType: 'NONE',
        manufacturer: seededPick(seed, 1, ['ABB', 'Alpitronic', 'Siemens eMobility']),
        model: seededPick(seed, 2, ['Terra 360', 'HYC400', 'Sicharge D']),
        serialNumber: `SN-${code}-${(seed % 100000).toString().padStart(5, '0')}`,
        installedAt: new Date(now - seededRange(seed, 3, 0.5, 4) * YEAR_MS),
        lastMaintenanceAt: new Date(now - seededRange(seed, 4, 10, 150) * 86_400_000),
        nextMaintenanceAt: new Date(now + seededRange(seed, 5, 30, 180) * 86_400_000),
        healthScore: Math.round(seededRange(seed, 6, 84, 99)),
        criticality: 'medium',
        status: 'online',
        customersServed: Math.round(seededRange(seed, 7, 2000, 12000)),
        seed,
        profileKey: 'ev',
        baselineLoadPct: seededRange(seed, 8, 40, 62),
        peakHour: 19,
        volatility: 0.09,
        agingFactor: 1,
        isFlexibleLoad: true,
        hasBatterySupport: false,
      })
    }
  }

  return { sites, assets }
}

/** Sensor fit-out per asset type. */
export const SENSOR_PLAN: Record<string, Array<{ kind: string; unit: string; min: number; max: number }>> = {
  transformer: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 420 },
    { kind: 'current', unit: 'A', min: 0, max: 5000 },
    { kind: 'temperature', unit: '°C', min: -10, max: 160 },
    { kind: 'load', unit: '%', min: 0, max: 180 },
    { kind: 'power_factor', unit: '', min: 0, max: 1 },
    { kind: 'thd', unit: '%', min: 0, max: 20 },
  ],
  substation: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 420 },
    { kind: 'current', unit: 'A', min: 0, max: 8000 },
    { kind: 'frequency', unit: 'Hz', min: 55, max: 65 },
    { kind: 'load', unit: '%', min: 0, max: 180 },
    { kind: 'temperature', unit: '°C', min: -10, max: 160 },
  ],
  power_plant: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 420 },
    { kind: 'current', unit: 'A', min: 0, max: 12000 },
    { kind: 'frequency', unit: 'Hz', min: 55, max: 65 },
    { kind: 'load', unit: '%', min: 0, max: 110 },
    { kind: 'temperature', unit: '°C', min: -10, max: 200 },
  ],
  transmission_line: [
    { kind: 'current', unit: 'A', min: 0, max: 4000 },
    { kind: 'voltage', unit: 'kV', min: 0, max: 420 },
    { kind: 'temperature', unit: '°C', min: -10, max: 120 },
    { kind: 'load', unit: '%', min: 0, max: 150 },
  ],
  solar_farm: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 145 },
    { kind: 'current', unit: 'A', min: 0, max: 6000 },
    { kind: 'load', unit: '%', min: 0, max: 105 },
    { kind: 'temperature', unit: '°C', min: -10, max: 95 },
  ],
  wind_farm: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 145 },
    { kind: 'current', unit: 'A', min: 0, max: 4000 },
    { kind: 'load', unit: '%', min: 0, max: 105 },
    { kind: 'temperature', unit: '°C', min: -10, max: 95 },
  ],
  battery_storage: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 145 },
    { kind: 'current', unit: 'A', min: -5000, max: 5000 },
    { kind: 'load', unit: '%', min: -105, max: 105 },
    { kind: 'temperature', unit: '°C', min: -10, max: 70 },
  ],
  industrial_load: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 145 },
    { kind: 'current', unit: 'A', min: 0, max: 6000 },
    { kind: 'load', unit: '%', min: 0, max: 130 },
    { kind: 'power_factor', unit: '', min: 0, max: 1 },
  ],
  ev_hub: [
    { kind: 'voltage', unit: 'kV', min: 0, max: 20 },
    { kind: 'current', unit: 'A', min: 0, max: 4000 },
    { kind: 'load', unit: '%', min: 0, max: 130 },
    { kind: 'power_factor', unit: '', min: 0, max: 1 },
  ],
}
