import Erdos1135.ND.Discrepancy.A5ReferenceND31FullCount
import Erdos1135.ND.Discrepancy.A5ReferenceNDM2
import Erdos1135.ND.Discrepancy.A5ReferenceAllSourceTStarL
import Erdos1135.ND.Discrepancy.A5ReferenceSection3GeometricBudget
import Erdos1135.Tao.Section3.AmbientScalePilot

/-!
# Powered main regime for ND-3.1

This leaf assembles the checked full-count splice at the second descending
ambient boundary.  One powered natural cutoff simultaneously clears the
ND-M2 threshold, the power-to-log threshold, and the source-support guard.

The zero and bounded-target cases remain outside this main-regime module.
-/

namespace Erdos1135
namespace ND

open Filter
open scoped Topology

noncomputable section

/-- The strict prefix below the first descending ambient boundary costs a
genuine power of the ambient endpoint. -/
theorem ceil_taoSection3AmbientBoundary_one_div_le_real_power
    {X : Real} (hX : 1 <= X) :
    (Nat.ceil (Tao.taoSection3AmbientBoundary X 1) : Real) / X <=
      2 * X ^ (-(1 / 32000 : Real)) := by
  have hXpos : 0 < X := zero_lt_one.trans_le hX
  have hyOne : 1 <= Tao.taoSection3AmbientBoundary X 1 :=
    Tao.taoSection3AmbientBoundary_one_le hX 1
  have hceil :
      (Nat.ceil (Tao.taoSection3AmbientBoundary X 1) : Real) <
        Tao.taoSection3AmbientBoundary X 1 + 1 :=
    Nat.ceil_lt_add_one
      (Tao.taoSection3AmbientBoundary_nonneg hXpos.le 1)
  have hceilTwo :
      (Nat.ceil (Tao.taoSection3AmbientBoundary X 1) : Real) <=
        2 * Tao.taoSection3AmbientBoundary X 1 := by
    linarith
  have hratio :
      Tao.taoSection3AmbientBoundary X 1 / X =
        X ^ (Tao.taoSection3AmbientRatio - 1) := by
    rw [Tao.taoSection3AmbientBoundary]
    simp only [pow_one]
    exact (Real.rpow_sub_one hXpos.ne'
      Tao.taoSection3AmbientRatio).symm
  have hexponent :
      Tao.taoSection3AmbientRatio - 1 <=
        -(1 / 32000 : Real) := by
    norm_num [Tao.taoSection3AmbientRatio, Tao.taoAlpha]
  calc
    (Nat.ceil (Tao.taoSection3AmbientBoundary X 1) : Real) / X <=
        (2 * Tao.taoSection3AmbientBoundary X 1) / X :=
      div_le_div_of_nonneg_right hceilTwo hXpos.le
    _ = 2 * X ^ (Tao.taoSection3AmbientRatio - 1) := by
      rw [mul_div_assoc, hratio]
    _ <= 2 * X ^ (-(1 / 32000 : Real)) :=
      mul_le_mul_of_nonneg_left
        (Real.rpow_le_rpow_of_exponent_le hX hexponent) (by norm_num)

/-- Above one powered natural cutoff, the second descending ambient boundary
feeds ND-M2 and the first boundary feeds the exact full-count block.  The
constant and cutoff are both selected before the target and counting
endpoint. -/
theorem exists_ndA5ReferenceND31MainRegime
    {c kappa d : Real} (hPhase : PhaseGap c kappa)
    (hd : 0 < d) (hd20 : d < 1 / 20)
    (hdk : d < 1 / (2 * kappa)) :
    ∃ Nstar : Nat, 2 <= Nstar ∧
      ∃ Cmain : Real, 0 <= Cmain ∧
        ∀ (N0 : Nat), Nstar <= N0 ->
          ∀ (X : Real), (N0 : Real) < X ->
            oddSyracuseBadRatio N0 X <=
              Cmain * (Real.log (N0 : Real)) ^ (-d) := by
  rcases ndA5ReferenceNDM2Bounds_sameD hPhase hd hd20 hdk with
    ⟨CHit, CTr, x0, hCHit, hCTr, hx0, hM2⟩
  rcases exists_ndA5ReferenceAllSourceTStarL hPhase hd hd20 hdk with
    ⟨CL, hCL, hAllSource⟩
  rcases eventually_atTop.1
      (eventually_rpow_neg_one_div_32000_le_log_rpow_neg d) with
    ⟨Qabs, hQabs⟩
  let r : Real := Tao.taoSection3AmbientRatio
  let e : Real := r ^ 2
  let E : Real := e ^ (-d)
  let Cprob : Real := (CHit + CTr) * E + CL
  let Cmain : Real := 2 + 2 * Cprob
  have he : 0 < e := by
    dsimp only [e, r]
    exact pow_pos Tao.taoSection3AmbientRatio_pos 2
  have hE : 0 <= E := by
    exact Real.rpow_nonneg he.le _
  have hCprob : 0 <= Cprob := by
    dsimp only [Cprob]
    exact add_nonneg (mul_nonneg (add_nonneg hCHit hCTr) hE) hCL
  have hCmain : 0 <= Cmain := by
    dsimp only [Cmain]
    positivity
  have hpow :
      Tendsto (fun N : Nat => (N : Real) ^ e) atTop atTop := by
    simpa only [Function.comp_def] using
      (tendsto_rpow_atTop he).comp tendsto_natCast_atTop_atTop
  have hlarge : ∀ᶠ N : Nat in atTop,
      2 <= N ∧ max x0 Qabs <= (N : Real) ^ e := by
    filter_upwards
        [eventually_ge_atTop (2 : Nat),
          hpow.eventually_ge_atTop (max x0 Qabs)]
      with N hN hcut
    exact ⟨hN, hcut⟩
  rcases eventually_atTop.1 hlarge with ⟨Nstar, hNstar⟩
  refine ⟨Nstar, (hNstar Nstar le_rfl).1, Cmain, hCmain, ?_⟩
  intro N0 hNstarN0 X hN0X
  rcases hNstar N0 hNstarN0 with ⟨hN0Two, hcutN0⟩
  have hN0OneNat : 1 <= N0 := by omega
  have hN0One : (1 : Real) <= (N0 : Real) := by exact_mod_cast hN0OneNat
  have hXOne : 1 <= X := hN0One.trans hN0X.le
  have hXpos : 0 < X := zero_lt_one.trans_le hXOne
  have hN0nonneg : (0 : Real) <= (N0 : Real) := Nat.cast_nonneg N0
  have hpowStrict : (N0 : Real) ^ e < X ^ e :=
    Real.rpow_lt_rpow hN0nonneg hN0X he
  let q : Real := Tao.taoSection3AmbientBoundary X 2
  let y : Real := transportSourceY q .alpha
  have hqEq : q = X ^ e := by
    rfl
  have hcutQ : max x0 Qabs <= q := by
    rw [hqEq]
    exact hcutN0.trans hpowStrict.le
  have hqx0 : x0 <= q := (le_max_left _ _).trans hcutQ
  have hqQabs : Qabs <= q := (le_max_right _ _).trans hcutQ
  have hqTwo : 2 <= q := hx0.trans hqx0
  have hq : 1 <= q := one_le_two.trans hqTwo
  have heOne : e <= 1 := by
    dsimp only [e, r]
    nlinarith [Tao.taoSection3AmbientRatio_pos,
      Tao.taoSection3AmbientRatio_lt_one]
  have hqX : q <= X := by
    rw [hqEq]
    calc
      X ^ e <= X ^ (1 : Real) :=
        Real.rpow_le_rpow_of_exponent_le hXOne heOne
      _ = X := by simp
  have hQabsX : Qabs <= X := hqQabs.trans hqX
  have hqy : q <= y := by
    dsimp only [y, transportSourceY]
    exact Real.self_le_rpow_of_one_le hq Tao.taoAlpha_one_lt.le
  have hyTwo : 2 <= y := hqTwo.trans hqy
  have hy : 1 <= y := one_le_two.trans hyTwo
  have hX0 : 0 <= X := zero_le_one.trans hXOne
  have hyBoundary : y = Tao.taoSection3AmbientBoundary X 1 := by
    dsimp only [y, q, transportSourceY, alpha]
    simpa only [Nat.reduceAdd] using
      Tao.taoSection3AmbientBoundary_succ_rpow hX0 1
  have hupper : y ^ alpha = X := by
    calc
      y ^ alpha =
          (Tao.taoSection3AmbientBoundary X 1) ^ Tao.taoAlpha := by
        rw [hyBoundary]
      _ = Tao.taoSection3AmbientBoundary X 0 := by
        simpa only [Nat.reduceAdd] using
          Tao.taoSection3AmbientBoundary_succ_rpow hX0 0
      _ = X := by
        simp [Tao.taoSection3AmbientBoundary]
  have hM2q := hM2 q hqx0 hq .alpha
  change
      ∃ hwindow : (oddBlock y).Nonempty,
        ∃ hmass : 0 < Tao.logFinsetMass (oddBlock y),
          uniformNoHitProbability q y hwindow <=
              CHit * q ^ (-(1 / 32000 : Real)) ∧
            passFullL1 q y hq hwindow hmass <=
              CTr * (Real.log q) ^ (-d) at hM2q
  rcases hM2q with ⟨hwindow, hmass, hHit, hPass⟩
  have hHarmonic :=
    hAllSource N0 hN0Two y hyTwo hmass
  have hCount :=
    oddSyracuseBadRatio_le_ceil_div_add_two_mul_fixedEventTerms
      hN0OneNat hq hy hXOne hupper hwindow hmass
  let R : Real := (Real.log (N0 : Real)) ^ (-d)
  have hN0OneStrict : (1 : Real) < (N0 : Real) := by
    exact_mod_cast (show 1 < N0 by omega)
  have hlogN0Pos : 0 < Real.log (N0 : Real) :=
    Real.log_pos hN0OneStrict
  have hlogNX : Real.log (N0 : Real) < Real.log X :=
    Real.log_lt_log (by positivity) hN0X
  have hlogXPos : 0 < Real.log X := hlogN0Pos.trans hlogNX
  have hXRate : (Real.log X) ^ (-d) <= R := by
    dsimp only [R]
    exact Real.rpow_le_rpow_of_nonpos hlogN0Pos hlogNX.le
      (neg_nonpos.mpr hd.le)
  have hBottomPower :
      (Nat.ceil y : Real) / X <=
        2 * X ^ (-(1 / 32000 : Real)) := by
    rw [hyBoundary]
    exact ceil_taoSection3AmbientBoundary_one_div_le_real_power hXOne
  have hBottom : (Nat.ceil y : Real) / X <= 2 * R := by
    calc
      (Nat.ceil y : Real) / X <=
          2 * X ^ (-(1 / 32000 : Real)) := hBottomPower
      _ <= 2 * (Real.log X) ^ (-d) :=
        mul_le_mul_of_nonneg_left (hQabs X hQabsX) (by norm_num)
      _ <= 2 * R := mul_le_mul_of_nonneg_left hXRate (by norm_num)
  have hqpos : 0 < q := zero_lt_one.trans_le hq
  have hlogqPos : 0 < Real.log q := Real.log_pos (one_lt_two.trans_le hqTwo)
  have hlogqEq : Real.log q = e * Real.log X := by
    rw [hqEq]
    exact Real.log_rpow hXpos e
  have hlogqRate : (Real.log q) ^ (-d) = E * (Real.log X) ^ (-d) := by
    rw [hlogqEq]
    dsimp only [E]
    exact Real.mul_rpow he.le hlogXPos.le
  have hlogqRateLe : (Real.log q) ^ (-d) <= E * R := by
    rw [hlogqRate]
    exact mul_le_mul_of_nonneg_left hXRate hE
  have hAbsorbQ := hQabs q hqQabs
  have hHitRate :
      uniformNoHitProbability q y hwindow <= CHit * E * R := by
    calc
      uniformNoHitProbability q y hwindow <=
          CHit * q ^ (-(1 / 32000 : Real)) := hHit
      _ <= CHit * (Real.log q) ^ (-d) :=
        mul_le_mul_of_nonneg_left hAbsorbQ hCHit
      _ <= CHit * (E * R) :=
        mul_le_mul_of_nonneg_left hlogqRateLe hCHit
      _ = CHit * E * R := by ring
  have hPassRate :
      passFullL1 q y hq hwindow hmass <= CTr * E * R := by
    calc
      passFullL1 q y hq hwindow hmass <=
          CTr * (Real.log q) ^ (-d) := hPass
      _ <= CTr * (E * R) :=
        mul_le_mul_of_nonneg_left hlogqRateLe hCTr
      _ = CTr * E * R := by ring
  have hTerms :
      uniformNoHitProbability q y hwindow +
          passFullL1 q y hq hwindow hmass +
          Tao.pmfProb (logOddBlockPMF y hmass)
            {N | N0 < syracuseOrbitMin N.1} <=
        Cprob * R := by
    calc
      uniformNoHitProbability q y hwindow +
            passFullL1 q y hq hwindow hmass +
            Tao.pmfProb (logOddBlockPMF y hmass)
              {N | N0 < syracuseOrbitMin N.1} <=
          CHit * E * R + CTr * E * R + CL * R :=
        add_le_add (add_le_add hHitRate hPassRate) hHarmonic
      _ = Cprob * R := by
        dsimp only [Cprob]
        ring
  calc
    oddSyracuseBadRatio N0 X <=
        (Nat.ceil y : Real) / X +
          2 *
            (uniformNoHitProbability q y hwindow +
              passFullL1 q y hq hwindow hmass +
              Tao.pmfProb (logOddBlockPMF y hmass)
                {N | N0 < syracuseOrbitMin N.1}) := hCount
    _ <= 2 * R + 2 * (Cprob * R) :=
      add_le_add hBottom
        (mul_le_mul_of_nonneg_left hTerms (by norm_num))
    _ = Cmain * R := by
      dsimp only [Cmain]
      ring
    _ = Cmain * (Real.log (N0 : Real)) ^ (-d) := by rfl

end

end ND
end Erdos1135
