import Erdos1135.Terras.Probability.BinomialTail
import Mathlib.Topology.Algebra.Order.Field

/-!
# Terras/Everett Asymptotic Counting Bridge

This module isolates the finite-to-asymptotic plumbing for the Terras/Everett parity-word count.
The remaining analytic work is now concentrated in one input: the high-odd-count binomial tail
ratio tends to zero.
-/

namespace Erdos1135
namespace Terras

open Filter

/-- Normalized count of contracting parity words of length `k`. -/
noncomputable def contractingWordRatio (k : ℕ) : ℝ :=
  (Fintype.card {w : ParityWord k // 3 ^ numOdd w < 2 ^ k} : ℝ) / (2 ^ k : ℝ)

/-- Normalized count of noncontracting parity words of length `k`. -/
noncomputable def noncontractingWordRatio (k : ℕ) : ℝ :=
  (Fintype.card {w : ParityWord k // ¬ 3 ^ numOdd w < 2 ^ k} : ℝ) / (2 ^ k : ℝ)

/-- Normalized binomial upper tail containing all noncontracting parity words. -/
noncomputable def highOddTailRatio (k : ℕ) : ℝ :=
  ((∑ r ∈ highOddCounts k, Nat.choose k r : ℕ) : ℝ) / (2 ^ k : ℝ)

lemma card_contracting_words_add_card_noncontracting_words (k : ℕ) :
    Fintype.card {w : ParityWord k // 3 ^ numOdd w < 2 ^ k} +
      Fintype.card {w : ParityWord k // ¬ 3 ^ numOdd w < 2 ^ k} = 2 ^ k := by
  classical
  let p : ParityWord k → Prop := fun w => 3 ^ numOdd w < 2 ^ k
  have hcompl := Fintype.card_subtype_compl p
  have hle : Fintype.card {w : ParityWord k // p w} ≤ 2 ^ k := by
    simpa [p, card_parityWord] using Fintype.card_subtype_le p
  change Fintype.card {w : ParityWord k // p w} +
    Fintype.card {w : ParityWord k // ¬ p w} = 2 ^ k
  rw [hcompl, card_parityWord]
  omega

theorem contractingWordRatio_eq_one_sub_noncontractingWordRatio (k : ℕ) :
    contractingWordRatio k = 1 - noncontractingWordRatio k := by
  have hsum := card_contracting_words_add_card_noncontracting_words k
  have hden : (2 ^ k : ℝ) ≠ 0 := by positivity
  have hsumR :
      (Fintype.card {w : ParityWord k // 3 ^ numOdd w < 2 ^ k} : ℝ) +
        (Fintype.card {w : ParityWord k // ¬ 3 ^ numOdd w < 2 ^ k} : ℝ) =
          (2 ^ k : ℝ) := by
    exact_mod_cast hsum
  unfold contractingWordRatio noncontractingWordRatio
  field_simp [hden]
  linarith

theorem noncontractingWordRatio_le_highOddTailRatio {k : ℕ} (hk : 0 < k) :
    noncontractingWordRatio k ≤ highOddTailRatio k := by
  have h := card_noncontracting_words_le_high_odd_tail hk
  have hR :
      (Fintype.card {w : ParityWord k // ¬ 3 ^ numOdd w < 2 ^ k} : ℝ) ≤
        ((∑ r ∈ highOddCounts k, Nat.choose k r : ℕ) : ℝ) := by
    exact_mod_cast h
  unfold noncontractingWordRatio highOddTailRatio
  gcongr

theorem highOddTailRatio_le_weighted_bound (k : ℕ) :
    highOddTailRatio k ≤
      (5 ^ k : ℝ) /
        ((2 ^ k : ℝ) *
          (3 ^ (3 * (k / 5)) * 2 ^ (k - 3 * (k / 5)) : ℕ)) := by
  let W : ℕ := 3 ^ (3 * (k / 5)) * 2 ^ (k - 3 * (k / 5))
  let S : ℕ := ∑ r ∈ highOddCounts k, Nat.choose k r
  have h := highOddCounts_sum_choose_mul_weight_lower_le_five_pow k
  have hR : (W : ℝ) * (S : ℝ) ≤ (5 ^ k : ℝ) := by
    exact_mod_cast h
  have hWpos : (0 : ℝ) < W := by positivity
  have h2pos : (0 : ℝ) < 2 ^ k := by positivity
  unfold highOddTailRatio
  change (S : ℝ) / (2 ^ k : ℝ) ≤ (5 ^ k : ℝ) / ((2 ^ k : ℝ) * (W : ℝ))
  field_simp [h2pos.ne', hWpos.ne']
  nlinarith

lemma five_pow_le_mod5_geometric_num (k : ℕ) :
    (5 ^ k : ℝ) ≤ (5 ^ 4 : ℝ) * ((5 ^ 5 : ℝ) ^ (k / 5)) := by
  have hmod : k % 5 < 5 := Nat.mod_lt k (by norm_num)
  have hk : k ≤ 5 * (k / 5) + 4 := by
    have hdiv := Nat.div_add_mod k 5
    omega
  have hpow : (5 : ℕ) ^ k ≤ 5 ^ (5 * (k / 5) + 4) := by
    exact Nat.pow_le_pow_right (by norm_num : 0 < (5 : ℕ)) hk
  have hpowR : (5 ^ k : ℝ) ≤ (5 ^ (5 * (k / 5) + 4) : ℕ) := by
    exact_mod_cast hpow
  calc
    (5 ^ k : ℝ) ≤ (5 ^ (5 * (k / 5) + 4) : ℕ) := hpowR
    _ = (5 ^ 4 : ℝ) * ((5 ^ 5 : ℝ) ^ (k / 5)) := by
      rw [show 5 * (k / 5) + 4 = 4 + 5 * (k / 5) by omega]
      rw [Nat.pow_add]
      norm_num
      rw [show (3125 : ℝ) = 5 ^ 5 by norm_num]
      rw [pow_mul]

lemma geometric_denominator_le_weight_denominator (k : ℕ) :
    (3 ^ (3 * (k / 5)) * 2 ^ (7 * (k / 5)) : ℝ) ≤
      (3 ^ (3 * (k / 5)) * 2 ^ (2 * k - 3 * (k / 5)) : ℕ) := by
  have h5q : 5 * (k / 5) ≤ k := Nat.mul_div_le k 5
  have h7 : 7 * (k / 5) ≤ 2 * k - 3 * (k / 5) := by omega
  have hpow : (2 : ℕ) ^ (7 * (k / 5)) ≤ 2 ^ (2 * k - 3 * (k / 5)) := by
    exact Nat.pow_le_pow_right (by norm_num : 0 < (2 : ℕ)) h7
  have hnat : 3 ^ (3 * (k / 5)) * 2 ^ (7 * (k / 5)) ≤
      3 ^ (3 * (k / 5)) * 2 ^ (2 * k - 3 * (k / 5)) := by
    exact Nat.mul_le_mul_left _ hpow
  exact_mod_cast hnat

lemma weighted_bound_denominator_eq (k : ℕ) :
    ((2 ^ k : ℝ) *
      (3 ^ (3 * (k / 5)) * 2 ^ (k - 3 * (k / 5)) : ℕ)) =
      (3 ^ (3 * (k / 5)) * 2 ^ (2 * k - 3 * (k / 5)) : ℕ) := by
  have hnat :
      (2 ^ k) * (3 ^ (3 * (k / 5)) * 2 ^ (k - 3 * (k / 5))) =
        3 ^ (3 * (k / 5)) * 2 ^ (2 * k - 3 * (k / 5)) := by
    have h5q : 5 * (k / 5) ≤ k := Nat.mul_div_le k 5
    have hk_sub : k + (k - 3 * (k / 5)) = 2 * k - 3 * (k / 5) := by omega
    rw [← mul_assoc]
    rw [mul_comm (2 ^ k) (3 ^ (3 * (k / 5)))]
    rw [mul_assoc]
    rw [← Nat.pow_add]
    rw [hk_sub]
  exact_mod_cast hnat

theorem highOddTailRatio_le_geometric_bound (k : ℕ) :
    highOddTailRatio k ≤ (625 : ℝ) * ((3125 : ℝ) / 3456) ^ (k / 5) := by
  have htail := highOddTailRatio_le_weighted_bound k
  have hnum := five_pow_le_mod5_geometric_num k
  have hden := geometric_denominator_le_weight_denominator k
  have hbound :
      (5 ^ k : ℝ) /
        ((2 ^ k : ℝ) *
          (3 ^ (3 * (k / 5)) * 2 ^ (k - 3 * (k / 5)) : ℕ)) ≤
        ((5 ^ 4 : ℝ) * ((5 ^ 5 : ℝ) ^ (k / 5))) /
          (3 ^ (3 * (k / 5)) * 2 ^ (7 * (k / 5))) := by
    rw [weighted_bound_denominator_eq]
    exact div_le_div₀ (by positivity) hnum (by positivity) hden
  calc
    highOddTailRatio k
        ≤ (5 ^ k : ℝ) /
          ((2 ^ k : ℝ) *
            (3 ^ (3 * (k / 5)) * 2 ^ (k - 3 * (k / 5)) : ℕ)) := htail
    _ ≤ ((5 ^ 4 : ℝ) * ((5 ^ 5 : ℝ) ^ (k / 5))) /
          (3 ^ (3 * (k / 5)) * 2 ^ (7 * (k / 5))) := hbound
    _ = (625 : ℝ) * ((3125 : ℝ) / 3456) ^ (k / 5) := by
      rw [show (625 : ℝ) = 5 ^ 4 by norm_num]
      rw [show (3125 : ℝ) = 5 ^ 5 by norm_num]
      rw [show (3456 : ℝ) = 3 ^ 3 * 2 ^ 7 by norm_num]
      rw [div_pow]
      rw [mul_div_assoc]
      congr 1
      rw [mul_pow, pow_mul, pow_mul]

lemma tendsto_nat_div_five_atTop :
    Tendsto (fun k : ℕ => k / 5) atTop atTop := by
  rw [Filter.tendsto_atTop]
  intro b
  exact eventually_atTop.mpr ⟨5 * b, fun k hk => by
    rw [Nat.le_div_iff_mul_le (by norm_num : 0 < 5)]
    omega⟩

theorem highOddTailRatio_tendsto_zero :
    Tendsto highOddTailRatio atTop (nhds 0) := by
  let a : ℝ := (3125 : ℝ) / 3456
  have ha_nonneg : 0 ≤ a := by positivity
  have ha_lt_one : a < 1 := by norm_num [a]
  have hpow : Tendsto (fun q : ℕ => a ^ q) atTop (nhds 0) :=
    tendsto_pow_atTop_nhds_zero_of_lt_one ha_nonneg ha_lt_one
  have hgeom : Tendsto (fun k : ℕ => (625 : ℝ) * a ^ (k / 5)) atTop (nhds 0) := by
    simpa [a] using (hpow.comp tendsto_nat_div_five_atTop).const_mul (625 : ℝ)
  refine squeeze_zero ?_ ?_ hgeom
  · intro k
    unfold highOddTailRatio
    positivity
  · intro k
    simpa [a] using highOddTailRatio_le_geometric_bound k

lemma noncontractingWordRatio_nonneg (k : ℕ) :
    0 ≤ noncontractingWordRatio k := by
  unfold noncontractingWordRatio
  positivity

theorem noncontractingWordRatio_tendsto_zero_of_highOddTailRatio_tendsto_zero
    (h : Tendsto highOddTailRatio atTop (nhds 0)) :
    Tendsto noncontractingWordRatio atTop (nhds 0) := by
  refine squeeze_zero' ?_ ?_ h
  · exact Filter.Eventually.of_forall noncontractingWordRatio_nonneg
  · exact eventually_atTop.mpr
      ⟨1, fun k hk => noncontractingWordRatio_le_highOddTailRatio (by omega)⟩

theorem contractingWordRatio_tendsto_one_of_noncontractingWordRatio_tendsto_zero
    (h : Tendsto noncontractingWordRatio atTop (nhds 0)) :
    Tendsto contractingWordRatio atTop (nhds 1) := by
  have hsub :
      Tendsto (fun k => (1 : ℝ) - noncontractingWordRatio k) atTop (nhds (1 - 0)) :=
    Filter.Tendsto.const_sub (1 : ℝ) h
  have hsub' :
      Tendsto (fun k => (1 : ℝ) - noncontractingWordRatio k) atTop (nhds 1) := by
    simpa using hsub
  exact Filter.Tendsto.congr'
    (Filter.Eventually.of_forall
      fun k => (contractingWordRatio_eq_one_sub_noncontractingWordRatio k).symm)
    hsub'

theorem contractingWordRatio_tendsto_one_of_highOddTailRatio_tendsto_zero
    (h : Tendsto highOddTailRatio atTop (nhds 0)) :
    Tendsto contractingWordRatio atTop (nhds 1) :=
  contractingWordRatio_tendsto_one_of_noncontractingWordRatio_tendsto_zero
    (noncontractingWordRatio_tendsto_zero_of_highOddTailRatio_tendsto_zero h)

theorem card_contracting_words_asymptotic_of_highOddTailRatio_tendsto_zero
    (h : Tendsto highOddTailRatio atTop (nhds 0)) :
    Tendsto
      (fun k =>
        ((Fintype.card {w : ParityWord k // 3 ^ numOdd w < 2 ^ k}) : ℝ)
          / 2 ^ k)
      atTop
      (nhds 1) := by
  simpa [contractingWordRatio] using
    contractingWordRatio_tendsto_one_of_highOddTailRatio_tendsto_zero h

theorem card_contracting_words_asymptotic :
    Tendsto
      (fun k =>
        ((Fintype.card {w : ParityWord k // 3 ^ numOdd w < 2 ^ k}) : ℝ)
          / 2 ^ k)
      atTop
      (nhds 1) :=
  card_contracting_words_asymptotic_of_highOddTailRatio_tendsto_zero
    highOddTailRatio_tendsto_zero

end Terras
end Erdos1135
