import Erdos1135.ND.Discrepancy.A5ReferenceND31Bridge
import Erdos1135.ND.LogTime.UniformScheduledNoHit

/-!
# Time-bounded fixed-target bridge for ND31

The top uniform source pays one literal Section 5 schedule to reach the
passage threshold.  Its totalized passage endpoint then pays the already
accumulated Section 3 fixed-target budget.  The two clocks add exactly.
-/

namespace Erdos1135
namespace ND

noncomputable section

/-- A bounded fixed-target bad event under `p` is charged by scheduled failure
to reach `Q`, one full-L1 passage discrepancy, and the remaining bounded bad
event under `q`. -/
theorem pmfProb_fixedTargetBadWithin_add_le
    {sigma : Type*} [Fintype sigma]
    (p q : PMF sigma) (value : sigma → ℕ)
    {b Q S T : ℕ} (hb : 1 ≤ b) (hQ : 1 ≤ Q) :
    Tao.pmfProb p
        {w | ¬ Tao.syracuseHitsAtMostWithin (value w) b (S + T)} ≤
      Tao.pmfProb p
          {w | ¬ Tao.syracuseHitsAtMostWithin (value w) Q S} +
        Tao.taoTV
          (p.map (fun w => Tao.syracusePassLocationAtMostOrOne Q
            (value w) hQ))
          (q.map (fun w => Tao.syracusePassLocationAtMostOrOne Q
            (value w) hQ)) +
        Tao.pmfProb q
          {w | ¬ Tao.syracuseHitsAtMostWithin (value w) b T} := by
  classical
  let pass : sigma → {M : ℕ // M ≤ Q} :=
    fun w => Tao.syracusePassLocationAtMostOrOne Q (value w) hQ
  let bad : Set sigma :=
    {w | ¬ Tao.syracuseHitsAtMostWithin (value w) b (S + T)}
  let noHit : Set sigma :=
    {w | ¬ Tao.syracuseHitsAtMostWithin (value w) Q S}
  let passBad : Set {M : ℕ // M ≤ Q} :=
    {M | ¬ Tao.syracuseHitsAtMostWithin M.1 b T}
  let targetBad : Set sigma :=
    {w | ¬ Tao.syracuseHitsAtMostWithin (value w) b T}
  have hsourceSubset : bad ⊆ noHit ∪ pass ⁻¹' passBad := by
    intro w hw
    by_cases hnoHit : w ∈ noHit
    · exact Or.inl hnoHit
    · apply Or.inr
      change ¬ Tao.syracuseHitsAtMostWithin (pass w).1 b T
      intro hpassGood
      apply hw
      have hhitQ : Tao.syracuseHitsAtMostWithin (value w) Q S := by
        simpa only [noHit, Set.mem_setOf_eq, not_not] using hnoHit
      exact Tao.syracuseHitsAtMostWithin_of_passLocationAtMostOrOne_add
        hQ hhitQ hpassGood
  have hpSource :
      Tao.pmfProb p bad ≤
        Tao.pmfProb p noHit + Tao.pmfProb (p.map pass) passBad := by
    calc
      Tao.pmfProb p bad ≤ Tao.pmfProb p (noHit ∪ pass ⁻¹' passBad) :=
        Tao.pmfProb_mono p hsourceSubset
      _ ≤ Tao.pmfProb p noHit + Tao.pmfProb p (pass ⁻¹' passBad) :=
        Tao.pmfProb_union_le_add p noHit (pass ⁻¹' passBad)
      _ = Tao.pmfProb p noHit + Tao.pmfProb (p.map pass) passBad := by
        rw [Tao.pmfProb_map_preimage]
  have hpassTV :
      Tao.pmfProb (p.map pass) passBad ≤
        Tao.taoTV (p.map pass) (q.map pass) +
          Tao.pmfProb (q.map pass) passBad := by
    have h := Tao.pmfProb_le_pmfProb_add_taoTV
      (q.map pass) (p.map pass) passBad
    rw [Tao.taoTV_comm] at h
    linarith
  have hpassSubset : pass ⁻¹' passBad ⊆ targetBad := by
    intro w hw
    change ¬ Tao.syracuseHitsAtMostWithin (value w) b T
    intro hsourceGood
    apply hw
    exact Tao.syracuseHitsAtMostWithin_passLocationAtMostOrOne
      hb hQ hsourceGood
  have hqPass :
      Tao.pmfProb (q.map pass) passBad ≤ Tao.pmfProb q targetBad := by
    rw [Tao.pmfProb_map_preimage]
    exact Tao.pmfProb_mono q hpassSubset
  change Tao.pmfProb p bad ≤
    Tao.pmfProb p noHit + Tao.taoTV (p.map pass) (q.map pass) +
      Tao.pmfProb q targetBad
  linarith

/-- ND block specialization.  The top source pays
`taoSection5N0 (floor q)` steps and the logarithmic source pays `T` more. -/
theorem pmfProb_uniformOddBlock_fixedTargetBadWithin_add_le
    {b T : ℕ} {q y : ℝ}
    (hb : 1 ≤ b) (hq : 1 ≤ q)
    (hwindow : (oddBlock y).Nonempty)
    (hmass : 0 < Tao.logFinsetMass (oddBlock y)) :
    Tao.pmfProb (uniformOddBlockPMF y hwindow)
        {N | ¬ Tao.syracuseHitsAtMostWithin N.1 b
          (Tao.taoSection5N0 (Nat.floor q) + T)} ≤
      uniformScheduledNoHitProbability q y hwindow +
        passFullL1 q y hq hwindow hmass +
        Tao.pmfProb (logOddBlockPMF y hmass)
          {N | ¬ Tao.syracuseHitsAtMostWithin N.1 b T} := by
  have hQ : 1 ≤ Nat.floor q := Tao.one_le_floor_of_one_le hq
  have h := pmfProb_fixedTargetBadWithin_add_le
    (uniformOddBlockPMF y hwindow) (logOddBlockPMF y hmass)
    (fun N => N.1) hb hQ
    (S := Tao.taoSection5N0 (Nat.floor q)) (T := T)
  simpa only [uniformScheduledNoHitProbability, passFullL1,
    uniformPassLaw, logPassLaw, passLocationOrOne,
    Tao.syracusePassLocationAtMostOrOne] using h

end


end ND
end Erdos1135
