import Erdos1135.Terras.EffectiveLogTimeStopping
import Mathlib.Analysis.Complex.ExponentialBounds

/-!
# A polynomial-rate Terras logarithmic-time corollary

The effective depth-`5m` estimate is converted here into one conventional
power-saving statement.  The constants are intentionally coarse: the point is
an end-to-end quantitative corollary, not optimization of the classical
Terras exponent.
-/

namespace Erdos1135
namespace Terras

open Filter
open scoped Topology

noncomputable section

/-- For the literal `log n` clock, the exponential part of the effective
threshold is already dominated by the branch threshold. -/
theorem effectiveLogTimeThreshold_one_five_mul_le
    (m : ℕ) :
    effectiveLogTimeThreshold 1 (5 * m) ≤ 3 ^ (5 * m) + 1 := by
  unfold effectiveLogTimeThreshold
  apply max_le
  · exact le_rfl
  · apply Nat.ceil_le.mpr
    have hexp :
        Real.exp (((5 * m : ℕ) : ℝ)) ≤
          (((3 ^ (5 * m) : ℕ) : ℝ)) := by
      calc
        Real.exp (((5 * m : ℕ) : ℝ)) =
            Real.exp 1 ^ (5 * m) := by
          simpa only [Nat.cast_mul, Nat.cast_ofNat, mul_one] using
            Real.exp_nat_mul (1 : ℝ) (5 * m)
        _ ≤ (3 : ℝ) ^ (5 * m) :=
          pow_le_pow_left₀ (Real.exp_nonneg 1)
            Real.exp_one_lt_three.le (5 * m)
        _ = (((3 ^ (5 * m) : ℕ) : ℝ)) := by norm_num
    simpa only [div_one] using hexp.trans
      (by exact_mod_cast
        (Nat.le_add_right (3 ^ (5 * m)) 1))

/-- The cutoff required at depth `5m` is at most `15552^m`. -/
theorem effectiveLogTimeThreshold_one_five_mul_cutoff_le
    {m : ℕ} (hm : 0 < m) :
    effectiveLogTimeThreshold 1 (5 * m) * 2 ^ (5 * m) ≤
      15552 ^ m := by
  have hone : 1 ≤ 3 ^ (5 * m) := by
    have hpos : 0 < 3 ^ (5 * m) := pow_pos (by norm_num) _
    omega
  have hdouble : 3 ^ (5 * m) + 1 ≤ 2 * 3 ^ (5 * m) := by
    omega
  have htwo : 2 ≤ 2 ^ m := by
    simpa only [pow_one] using
      Nat.pow_le_pow_right (by norm_num : 0 < (2 : ℕ)) hm
  calc
    effectiveLogTimeThreshold 1 (5 * m) * 2 ^ (5 * m) ≤
        (3 ^ (5 * m) + 1) * 2 ^ (5 * m) :=
      Nat.mul_le_mul_right _ (effectiveLogTimeThreshold_one_five_mul_le m)
    _ ≤ (2 * 3 ^ (5 * m)) * 2 ^ (5 * m) :=
      Nat.mul_le_mul_right _ hdouble
    _ = 2 * 7776 ^ m := by
      simp only [pow_mul]
      rw [mul_assoc, ← mul_pow]
      norm_num
    _ ≤ 2 ^ m * 7776 ^ m := Nat.mul_le_mul_right _ htwo
    _ = 15552 ^ m := by
      rw [← mul_pow]
      norm_num

private theorem terras_geometric_base_le_hundredth_root :
    (3125 : ℝ) / 3456 ≤ (15552 : ℝ) ^ (-(1 / 100 : ℝ)) := by
  have hleft : 0 ≤ (3125 : ℝ) / 3456 := by positivity
  have hright : 0 ≤ (15552 : ℝ) ^ (-(1 / 100 : ℝ)) :=
    Real.rpow_nonneg (by norm_num) _
  apply (pow_le_pow_iff_left₀ hleft hright
    (by norm_num : (100 : ℕ) ≠ 0)).mp
  have hrpow :
      ((15552 : ℝ) ^ (-(1 / 100 : ℝ))) ^ (100 : ℕ) =
        1 / 15552 := by
    rw [← Real.rpow_mul_natCast (by norm_num : (0 : ℝ) ≤ 15552)]
    norm_num [Real.rpow_neg (by norm_num : (0 : ℝ) ≤ 15552)]
  rw [hrpow]
  norm_num

private theorem terras_three_term_geometric_le
    (m : ℕ) :
    1 / (32 : ℝ) ^ m +
        625 * ((3125 : ℝ) / 3456) ^ m +
        1 / (243 : ℝ) ^ m ≤
      627 * ((3125 : ℝ) / 3456) ^ m := by
  have hq0 : 0 ≤ (3125 : ℝ) / 3456 := by positivity
  have h32 : (1 : ℝ) / 32 ≤ 3125 / 3456 := by norm_num
  have h243 : (1 : ℝ) / 243 ≤ 3125 / 3456 := by norm_num
  have h32pow : ((1 : ℝ) / 32) ^ m ≤
      ((3125 : ℝ) / 3456) ^ m :=
    pow_le_pow_left₀ (by positivity) h32 m
  have h243pow : ((1 : ℝ) / 243) ^ m ≤
      ((3125 : ℝ) / 3456) ^ m :=
    pow_le_pow_left₀ (by positivity) h243 m
  simp only [← one_div_pow]
  nlinarith [pow_nonneg hq0 m]

private theorem terras_geometric_log_depth_le_power
    {N : ℕ} (hN : 15552 ≤ N) :
    ((3125 : ℝ) / 3456) ^ (Nat.log 15552 N) ≤
      15552 * (N : ℝ) ^ (-(1 / 100 : ℝ)) := by
  let m := Nat.log 15552 N
  let q : ℝ := (3125 : ℝ) / 3456
  let b : ℝ := 15552
  have hNposNat : 0 < N := by omega
  have hNpos : 0 < (N : ℝ) := by exact_mod_cast hNposNat
  have hbOne : 1 ≤ b := by norm_num [b]
  have hbp : 0 < b := zero_lt_one.trans_le hbOne
  have hb0 : 0 ≤ b := zero_le_one.trans hbOne
  have hroot : q ≤ b ^ (-(1 / 100 : ℝ)) := by
    simpa only [q, b] using terras_geometric_base_le_hundredth_root
  have hq0 : 0 ≤ q := by positivity
  have hqm :
      q ^ m ≤ b ^ (-(1 / 100 : ℝ) * (m : ℝ)) := by
    calc
      q ^ m ≤ (b ^ (-(1 / 100 : ℝ))) ^ m :=
        pow_le_pow_left₀ hq0 hroot m
      _ = b ^ (-(1 / 100 : ℝ) * (m : ℝ)) := by
        symm
        exact Real.rpow_mul_natCast hb0 _ m
  have hNupperNat : N < 15552 ^ (m + 1) := by
    simpa only [m, Nat.succ_eq_add_one] using
      Nat.lt_pow_succ_log_self (by norm_num : 1 < (15552 : ℕ)) N
  have hNupper : (N : ℝ) ≤ b ^ (m + 1 : ℕ) := by
    have hcast : (N : ℝ) ≤ ((15552 ^ (m + 1) : ℕ) : ℝ) := by
      exact_mod_cast hNupperNat.le
    simpa only [b, Nat.cast_pow, Nat.cast_ofNat] using hcast
  have htail :
      b ^ (-(1 / 100 : ℝ) * ((m : ℝ) + 1)) ≤
        (N : ℝ) ^ (-(1 / 100 : ℝ)) := by
    have hrev := Real.rpow_le_rpow_of_nonpos hNpos hNupper
      (by norm_num : -(1 / 100 : ℝ) ≤ 0)
    have hrexp :
        (b ^ (m + 1 : ℕ)) ^ (-(1 / 100 : ℝ)) =
          b ^ (-(1 / 100 : ℝ) * ((m : ℝ) + 1)) := by
      calc
        (b ^ (m + 1 : ℕ)) ^ (-(1 / 100 : ℝ)) =
            b ^ (((m + 1 : ℕ) : ℝ) * (-(1 / 100 : ℝ))) := by
          symm
          exact Real.rpow_natCast_mul hb0 (m + 1) _
        _ = b ^ (-(1 / 100 : ℝ) * ((m : ℝ) + 1)) := by
          congr 1
          push_cast
          ring
    simpa only [hrexp] using hrev
  have hhead : b ^ (1 / 100 : ℝ) ≤ b := by
    simpa only [Real.rpow_one] using
      Real.rpow_le_rpow_of_exponent_le hbOne
        (by norm_num : (1 / 100 : ℝ) ≤ 1)
  calc
    ((3125 : ℝ) / 3456) ^ (Nat.log 15552 N) = q ^ m := rfl
    _ ≤ b ^ (-(1 / 100 : ℝ) * (m : ℝ)) := hqm
    _ = b ^ (1 / 100 : ℝ) *
        b ^ (-(1 / 100 : ℝ) * ((m : ℝ) + 1)) := by
      rw [← Real.rpow_add hbp]
      congr 1
      ring
    _ ≤ b * (N : ℝ) ^ (-(1 / 100 : ℝ)) :=
      mul_le_mul hhead htail
        (Real.rpow_nonneg hb0 _)
        (zero_le_one.trans hbOne)
    _ = 15552 * (N : ℝ) ^ (-(1 / 100 : ℝ)) := by rfl

/-- Almost every starting value descends within `log n` accelerated steps,
with an explicit power-saving exceptional proportion.  The threshold and
constant are deliberately rounded for a short public statement. -/
theorem natCountingRatio_finiteStoppingTime_log_failure_le_power
    {N : ℕ} (hN : 15552 ≤ N) :
    natCountingRatio
        {n : ℕ | ¬ ∃ k : ℕ,
          (k : ℝ) ≤ Real.log (n : ℝ) ∧ accelerated^[k] n < n}
        N ≤
      10000000 * (N : ℝ) ^ (-(1 / 100 : ℝ)) := by
  let m := Nat.log 15552 N
  have hm : 0 < m := by
    dsimp only [m]
    exact Nat.log_pos (by norm_num) hN
  have hcutoff :
      effectiveLogTimeThreshold 1 (5 * m) * 2 ^ (5 * m) ≤ N := by
    exact (effectiveLogTimeThreshold_one_five_mul_cutoff_le hm).trans
      (Nat.pow_log_le_self 15552 (by omega))
  have hmain :=
    natCountingRatio_finiteStoppingTime_log_failure_le_five_mul hm hcutoff
  have hthree := terras_three_term_geometric_le m
  have hpower := terras_geometric_log_depth_le_power hN
  calc
    natCountingRatio
        {n : ℕ | ¬ ∃ k : ℕ,
          (k : ℝ) ≤ Real.log (n : ℝ) ∧ accelerated^[k] n < n}
        N ≤
        1 / (32 : ℝ) ^ m +
          625 * ((3125 : ℝ) / 3456) ^ m +
          1 / (243 : ℝ) ^ m := hmain
    _ ≤ 627 * ((3125 : ℝ) / 3456) ^ m := hthree
    _ ≤ 627 * (15552 * (N : ℝ) ^ (-(1 / 100 : ℝ))) :=
      mul_le_mul_of_nonneg_left hpower (by norm_num)
    _ ≤ 10000000 * (N : ℝ) ^ (-(1 / 100 : ℝ)) := by
      have hpow0 : 0 ≤ (N : ℝ) ^ (-(1 / 100 : ℝ)) :=
        Real.rpow_nonneg (by positivity) _
      nlinarith

end

end Terras
end Erdos1135
