import Erdos1135.ND.LogTime.FixedTargetBridge
import Erdos1135.Tao.Section3.TimeBoundedGeometricBudget

/-!
# Public Syracuse logarithmic clock

The terminal Section 3 trace pays one final top-block passage schedule.  This
leaf bounds that sum first by `log X`, then uniformly by `log N` for every
integer in the top ambient block.
-/

namespace Erdos1135
namespace ND

noncomputable section

/-- Coefficient before converting the ambient endpoint logarithm to a
pointwise source logarithm. -/
noncomputable def ndSyracuseAmbientTimeConstant : ℝ :=
  Tao.taoSection3ForwardTimeConstant + 1 / (10 * Real.log 2)

/-- Public Syracuse-time constant.  The exact factor `alpha = 1001/1000`
converts the ambient endpoint logarithm to the pointwise source logarithm. -/
noncomputable def ndSyracuseLogTimeConstant : ℝ :=
  Tao.taoAlpha * ndSyracuseAmbientTimeConstant

theorem ndSyracuseAmbientTimeConstant_pos :
    0 < ndSyracuseAmbientTimeConstant := by
  unfold ndSyracuseAmbientTimeConstant
  have hlogTwo : 0 < Real.log (2 : ℝ) := Real.log_pos (by norm_num)
  exact add_pos Tao.taoSection3ForwardTimeConstant_pos
    (one_div_pos.mpr (mul_pos (by norm_num) hlogTwo))

theorem ndSyracuseLogTimeConstant_pos :
    0 < ndSyracuseLogTimeConstant := by
  unfold ndSyracuseLogTimeConstant
  exact mul_pos Tao.taoAlpha_pos ndSyracuseAmbientTimeConstant_pos

/-- One final Section 5 schedule plus the terminal Section 3 clock is bounded
by the ambient endpoint logarithm. -/
theorem ndTopPassageBudget_cast_le_ambientLog
    {X : ℝ} (hX : 1 ≤ X) {T : ℕ}
    (hT : (T : ℝ) ≤
      Tao.taoSection3ForwardTimeConstant * Real.log X) :
    ((Tao.taoSection5N0
          (Nat.floor (Tao.taoSection3AmbientBoundary X 2)) + T : ℕ) : ℝ) ≤
      ndSyracuseAmbientTimeConstant * Real.log X := by
  let q := Tao.taoSection3AmbientBoundary X 2
  have hXpos : 0 < X := zero_lt_one.trans_le hX
  have hqOne : 1 ≤ q := Tao.taoSection3AmbientBoundary_one_le hX 2
  have hqPos : 0 < q := zero_lt_one.trans_le hqOne
  have hqNonneg : 0 ≤ q := hqPos.le
  have hfloorPos : 0 < ((Nat.floor q : ℕ) : ℝ) := by
    exact_mod_cast (show 0 < Nat.floor q by
      exact Nat.zero_lt_of_lt (Tao.one_le_floor_of_one_le hqOne))
  have hlogFloorLe :
      Real.log ((Nat.floor q : ℕ) : ℝ) ≤ Real.log q :=
    Real.strictMonoOn_log.monotoneOn hfloorPos hqPos (Nat.floor_le hqNonneg)
  have hratioSq : Tao.taoSection3AmbientRatio ^ 2 ≤ 1 :=
    pow_le_one₀ Tao.taoSection3AmbientRatio_pos.le
      Tao.taoSection3AmbientRatio_lt_one.le
  have hqX : q ≤ X := by
    dsimp only [q]
    unfold Tao.taoSection3AmbientBoundary
    exact Real.rpow_le_self_of_one_le hX hratioSq
  have hlogqLe : Real.log q ≤ Real.log X :=
    Real.strictMonoOn_log.monotoneOn hqPos hXpos hqX
  have hden : 0 < 10 * Real.log 2 := by positivity
  have hschedule :
      (Tao.taoSection5N0 (Nat.floor q) : ℝ) ≤
        Real.log X / (10 * Real.log 2) := by
    calc
      (Tao.taoSection5N0 (Nat.floor q) : ℝ) ≤
          Real.log ((Nat.floor q : ℕ) : ℝ) /
            (10 * Real.log 2) :=
        Tao.taoSection5N0_le_log_div_ten_log_two (Nat.floor q)
      _ ≤ Real.log q / (10 * Real.log 2) :=
        div_le_div_of_nonneg_right hlogFloorLe hden.le
      _ ≤ Real.log X / (10 * Real.log 2) :=
        div_le_div_of_nonneg_right hlogqLe hden.le
  have hsum :
      (Tao.taoSection5N0 (Nat.floor q) : ℝ) + (T : ℝ) ≤
        ndSyracuseAmbientTimeConstant * Real.log X := by
    unfold ndSyracuseAmbientTimeConstant
    calc
      (Tao.taoSection5N0 (Nat.floor q) : ℝ) + (T : ℝ) ≤
        Real.log X / (10 * Real.log 2) +
          Tao.taoSection3ForwardTimeConstant * Real.log X :=
        add_le_add hschedule hT
      _ = (Tao.taoSection3ForwardTimeConstant +
            1 / (10 * Real.log 2)) * Real.log X := by ring
  simpa only [q, Nat.cast_add] using hsum

/-- Every integer in the terminal top block receives the same accumulated
budget inside the public pointwise `C * log N` allowance. -/
theorem ndTopPassageBudget_cast_le_pointwiseLog
    {X : ℝ} (hX : 1 ≤ X) {N T : ℕ}
    (hN : Nat.ceil (Tao.taoSection3AmbientBoundary X 1) ≤ N)
    (hT : (T : ℝ) ≤
      Tao.taoSection3ForwardTimeConstant * Real.log X) :
    ((Tao.taoSection5N0
          (Nat.floor (Tao.taoSection3AmbientBoundary X 2)) + T : ℕ) : ℝ) ≤
      ndSyracuseLogTimeConstant * Real.log (N : ℝ) := by
  have hambient := ndTopPassageBudget_cast_le_ambientLog hX hT
  have hXpos : 0 < X := zero_lt_one.trans_le hX
  let y := Tao.taoSection3AmbientBoundary X 1
  have hyOne : 1 ≤ y := Tao.taoSection3AmbientBoundary_one_le hX 1
  have hyPos : 0 < y := zero_lt_one.trans_le hyOne
  have hyN : y ≤ (N : ℝ) := by
    exact (Nat.le_ceil y).trans (by exact_mod_cast hN)
  have hNpos : 0 < (N : ℝ) := hyPos.trans_le hyN
  have hlogyN : Real.log y ≤ Real.log (N : ℝ) :=
    Real.strictMonoOn_log.monotoneOn hyPos hNpos hyN
  have hlogy : Real.log y =
      Tao.taoSection3AmbientRatio * Real.log X := by
    dsimp only [y]
    unfold Tao.taoSection3AmbientBoundary
    simp only [pow_one]
    exact Real.log_rpow hXpos Tao.taoSection3AmbientRatio
  have halphaRatio :
      Tao.taoAlpha * Tao.taoSection3AmbientRatio = 1 := by
    norm_num [Tao.taoSection3AmbientRatio, Tao.taoAlpha]
  have hlogX : Real.log X = Tao.taoAlpha * Real.log y := by
    rw [hlogy, ← mul_assoc, halphaRatio, one_mul]
  have hlogXLeN :
      Real.log X ≤ Tao.taoAlpha * Real.log (N : ℝ) := by
    rw [hlogX]
    exact mul_le_mul_of_nonneg_left hlogyN Tao.taoAlpha_pos.le
  have hbaseNonneg : 0 ≤ ndSyracuseAmbientTimeConstant :=
    ndSyracuseAmbientTimeConstant_pos.le
  calc
    ((Tao.taoSection5N0
          (Nat.floor (Tao.taoSection3AmbientBoundary X 2)) + T : ℕ) : ℝ) ≤
        ndSyracuseAmbientTimeConstant * Real.log X := hambient
    _ ≤ ndSyracuseAmbientTimeConstant *
          (Tao.taoAlpha * Real.log (N : ℝ)) :=
      mul_le_mul_of_nonneg_left hlogXLeN hbaseNonneg
    _ = ndSyracuseLogTimeConstant * Real.log (N : ℝ) := by
      unfold ndSyracuseLogTimeConstant
      ring

end


end ND
end Erdos1135
