uint32_t minutesToMs(uint16_t minutes) {
  if (minutes < 1) minutes = 1;
  return (uint32_t)minutes * 60000UL;
}

uint32_t clampInterval(uint32_t value, uint32_t minValue, uint32_t maxValue) {
  if (value < minValue) return minValue;
  if (value > maxValue) return maxValue;
  return value;
}

void setStripOff(int s) {
  if (s < 0 || s >= MAX_STRIPS) return;
  for (int i = 0; i < ledCount[s]; i++) {
    ledState[s][i] = false;
    leds[s][i] = CRGB::Black;
  }
}

int countStripOn(int s) {
  int cnt = 0;
  for (int i = 0; i < ledCount[s]; i++) {
    if (ledState[s][i]) cnt++;
  }
  return cnt;
}

int countUsableLeds(int s) {
  int cnt = 0;
  for (int i = 0; i < ledCount[s]; i++) {
    if (config[s][i].mode != 0) cnt++;
  }
  return cnt;
}

void turnRandomLedOn(int s) {
  if (ledCount[s] == 0) return;

  for (int tries = 0; tries < 20; tries++) {
    int i = random(0, ledCount[s]);
    if (!ledState[s][i] && config[s][i].mode != 0) {
      ledState[s][i] = true;
      nextEffectUpdate[s][i] = 0;
      applyLedMode(s, i);
      return;
    }
  }
}

void turnRandomLedOff(int s) {
  if (ledCount[s] == 0) return;

  for (int tries = 0; tries < 20; tries++) {
    int i = random(0, ledCount[s]);
    if (ledState[s][i]) {
      ledState[s][i] = false;
      leds[s][i] = CRGB::Black;
      return;
    }
  }
}

void toggleRandomLed(int s) {
  if (ledCount[s] == 0) return;

  int usable = max(1, countUsableLeds(s));
  int onCount = countStripOn(s);
  int targetMin = max(1, usable / 3);          // ca. 33%
  int targetMax = max(1, (usable * 2) / 3);    // ca. 66%

  if (onCount < targetMin) {
    turnRandomLedOn(s);
  } else if (onCount > targetMax) {
    turnRandomLedOff(s);
  } else {
    if (random8() < 140) turnRandomLedOn(s);
    else turnRandomLedOff(s);
  }
}

void startRandomHouse(int s) {
  if (s < 0 || s >= MAX_STRIPS) return;
  if (ledCount[s] == 0) return;

  setStripOff(s);
  randomState[s].running = true;
  randomState[s].night = true;
  randomState[s].phaseStart = millis();
  randomState[s].nextAction = millis() + random(500, 2000);

  Serial.print("Random hus START - Baand ");
  Serial.println(stripName(s));
}

void stopRandomHouse(int s) {
  if (s < 0 || s >= MAX_STRIPS) return;

  randomState[s].running = false;
  setStripOff(s);
  FastLED.show();

  Serial.print("Random hus STOP - Baand ");
  Serial.println(stripName(s));
}

bool handleRandomDccAddress(int cs2Addr, int direction) {
  bool found = false;

  for (int s = 0; s < MAX_STRIPS; s++) {
    if (randomConfig[s].dccAddress == cs2Addr) {
      found = true;
      if (direction) startRandomHouse(s);
      else stopRandomHouse(s);
    }
  }

  return found;
}

void updateRandomHouse() {
  uint32_t now = millis();
  bool changed = false;

  for (int s = 0; s < MAX_STRIPS; s++) {
    if (!randomState[s].running) continue;
    if (ledCount[s] == 0) continue;

    uint32_t phaseLength = randomState[s].night ? minutesToMs(randomNightMinutes) : minutesToMs(randomDayMinutes);
    uint32_t elapsed = now - randomState[s].phaseStart;

    if (elapsed >= phaseLength) {
      randomState[s].night = !randomState[s].night;
      randomState[s].phaseStart = now;

      if (randomState[s].night) {
        // Ny nat: alt starter slukket og tændes hurtigt i begyndelsen.
        setStripOff(s);
        randomState[s].nextAction = now + random(500, 2000);
        Serial.print("Random hus NAT - Baand ");
        Serial.println(stripName(s));
      } else {
        // Dag: sikkerhedssluk. Normalt er lyset allerede slukket gradvist i slutningen af natten.
        setStripOff(s);
        randomState[s].nextAction = now + 10000;
        Serial.print("Random hus DAG - Baand ");
        Serial.println(stripName(s));
      }
      changed = true;
      continue;
    }

    if (!randomState[s].night) continue;
    if (now < randomState[s].nextAction) continue;

    // Natten opdeles i tre faser:
    // 1) Første 25%: tænd lysene ret hurtigt.
    //    Ved 2 minutters nat svarer det til ca. 30 sekunder.
    // 2) Midterperioden: rolig tilfældig aktivitet.
    // 3) Sidste 17%: sluk gradvist.
    //    Ved 2 minutters nat svarer det til ca. 20 sekunder.
    uint32_t turnOnPeriod  = max(10000UL, phaseLength / 4UL);
    uint32_t turnOffPeriod = max(8000UL,  phaseLength / 6UL);
    uint32_t turnOffStart  = phaseLength - turnOffPeriod;

    if (elapsed < turnOnPeriod) {
      int usable = max(1, countUsableLeds(s));
      int targetOn = max(1, (usable * 3) / 5);  // ca. 60% tændt ved aftenstart
      if (countStripOn(s) < targetOn) {
        turnRandomLedOn(s);
        changed = true;
      }
      uint32_t interval = turnOnPeriod / (uint32_t)(targetOn + 1);
      randomState[s].nextAction = now + clampInterval(interval, 700, 6000);

    } else if (elapsed >= turnOffStart) {
      int onCount = countStripOn(s);
      if (onCount > 0) {
        turnRandomLedOff(s);
        changed = true;
      }
      uint32_t remaining = max(1000UL, phaseLength - elapsed);
      uint32_t interval = remaining / (uint32_t)(max(1, onCount) + 1);
      randomState[s].nextAction = now + clampInterval(interval, 500, 4000);

    } else {
      toggleRandomLed(s);
      changed = true;
      randomState[s].nextAction = now + random(12000, 35000);
    }
  }

  if (changed) FastLED.show();
}
