-- Mathlib/CategoryTheory/Limits/VanKampen.lean
theorem isVanKampenColimit_extendCofan {n : ℕ} (f : Fin (n + 1) → C)
    {c₁ : Cofan fun i : Fin n ↦ f i.succ} {c₂ : BinaryCofan (f 0) c₁.pt}
    (t₁ : IsVanKampenColimit c₁) (t₂ : IsVanKampenColimit c₂)
    [∀ {Z} (i : Z ⟶ c₂.pt), HasPullback c₂.inr i]
    [HasFiniteCoproducts C] :
    IsVanKampenColimit (extendCofan c₁ c₂)

Proof state:
case refine_1.w.h.mk.right.h
C : Type u
inst✝² : Category.{v, u} C
n : ℕ
f : Fin (n + 1) → C
c₁ : Cofan fun i => f i.succ
c₂ : BinaryCofan (f 0) c₁.pt
t₁ : IsVanKampenColimit c₁
t₂ : IsVanKampenColimit c₂
inst✝¹ : ∀ {Z : C} (i : Z ⟶ c₂.pt), HasPullback c₂.inr i
inst✝ : HasFiniteCoproducts C
F : Discrete (Fin (n + 1)) ⥤ C
c : Cocone F
α : F ⟶ Discrete.functor f
i : c.pt ⟶ (extendCofan c₁ c₂).pt
e : α ≫ (extendCofan c₁ c₂).ι = c.ι ≫ (Functor.const (Discrete (Fin (n + 1)))).map i
hα : NatTrans.Equifibered α
Hc : IsColimit c
j✝ : Fin (n + 1)
j : Fin n
⊢ Sigma.ι (fun j => F.obj { as := j.succ }) j ≫ (Sigma.desc fun b => α.app { as := b.succ } ≫ c₁.inj b) ≫ c₂.inr =
    Sigma.ι (fun j => F.obj { as := j.succ }) j ≫ (Sigma.desc fun b => c.ι.app { as := b.succ }) ≫ i

Tactic:
simpa only [colimit.ι_desc_assoc, Discrete.functor_obj, Cofan.mk_pt, Cofan.mk_ι_app,
  Category.assoc, extendCofan_pt, Functor.const_obj_obj, NatTrans.comp_app, extendCofan_ι_app,
  Fin.cases_succ, Functor.const_map_app] using congr_app e ⟨j.succ⟩

Result:
no goals

Proof state:
case refine_3.succ.refine_2
C : Type u
inst✝² : Category.{v, u} C
n : ℕ
f : Fin (n + 1) → C
c₁ : Cofan fun i => f i.succ
c₂ : BinaryCofan (f 0) c₁.pt
t₁ : IsVanKampenColimit c₁
t₂ : IsVanKampenColimit c₂
inst✝¹ : ∀ {Z : C} (i : Z ⟶ c₂.pt), HasPullback c₂.inr i
inst✝ : HasFiniteCoproducts C
F : Discrete (Fin (n + 1)) ⥤ C
c : Cocone F
α : F ⟶ Discrete.functor f
i : c.pt ⟶ (extendCofan c₁ c₂).pt
e : α ≫ (extendCofan c₁ c₂).ι = c.ι ≫ (Functor.const (Discrete (Fin (n + 1)))).map i
hα : NatTrans.Equifibered α
Hc : IsColimit c
t₂' :
  ∀ (j : Discrete WalkingPair),
    IsPullback ((BinaryCofan.mk (c.ι.app { as := 0 }) (Sigma.desc fun b => c.ι.app { as := b.succ })).ι.app j)
      ((mapPair (α.app { as := 0 }) (Sigma.desc fun b => α.app { as := b.succ } ≫ c₁.inj b)).app j) i (c₂.ι.app j)
j : Fin n
a✝ :
  IsPullback (c.ι.app { as := j.castSucc }) (α.app { as := j.castSucc }) i
    ((extendCofan c₁ c₂).ι.app { as := j.castSucc })
t₁' :
  IsPullback
    ((Cofan.mk (colimit.cocone (Discrete.functor fun j => F.obj { as := j.succ })).1
            (Sigma.ι fun j => F.obj { as := j.succ })).ι.app
      { as := j })
    ((Discrete.natTrans fun i => α.app { as := i.as.succ }).app { as := j })
    (Sigma.desc fun j => α.app { as := j.succ } ≫ c₁.inj j) (c₁.ι.app { as := j })
⊢ IsPullback (c.ι.app { as := j.succ }) (α.app { as := j.succ }) i ((extendCofan c₁ c₂).ι.app { as := j.succ })

Tactic:
simpa [Functor.const_obj_obj, Discrete.functor_obj, extendCofan_pt, extendCofan_ι_app,
  Fin.cases_succ, BinaryCofan.mk_pt, colimit.cocone_x, Cofan.mk_pt, Cofan.mk_ι_app,
  BinaryCofan.ι_app_right, BinaryCofan.mk_inr, colimit.ι_desc,
  Discrete.natTrans_app] using t₁'.paste_horiz (t₂' ⟨WalkingPair.right⟩)

Result:
no goals

Proof state:
case refine_2.uniq
C : Type u
inst✝² : Category.{v, u} C
n : ℕ
f : Fin (n + 1) → C
c₁ : Cofan fun i => f i.succ
c₂ : BinaryCofan (f 0) c₁.pt
t₁ : IsVanKampenColimit c₁
t₂ : IsVanKampenColimit c₂
inst✝¹ : ∀ {Z : C} (i : Z ⟶ c₂.pt), HasPullback c₂.inr i
inst✝ : HasFiniteCoproducts C
j : Fin (n + 1)
F' : Fin (n + 1) → C
c : Cocone (Discrete.functor F')
α : Discrete.functor F' ⟶ Discrete.functor f
i : c.pt ⟶ (extendCofan c₁ c₂).pt
e : α ≫ (extendCofan c₁ c₂).ι = c.ι ≫ (Functor.const (Discrete (Fin (n + 1)))).map i
hα : NatTrans.Equifibered α
Hc : IsColimit c
T : C
f₁ : F' 0 ⟶ T
f₂ : (∐ fun j => (Discrete.functor F').obj { as := j.succ }) ⟶ T
f₃ : (BinaryCofan.mk (c.ι.app { as := 0 }) (Sigma.desc fun b => c.ι.app { as := b.succ })).pt ⟶ T
m₁ : c.ι.app { as := 0 } ≫ f₃ = f₁
m₂ : (Sigma.desc fun b => c.ι.app { as := b.succ }) ≫ f₃ = f₂
⊢ ∀ (j : Discrete (Fin (n + 1))),
    c.ι.app j ≫ f₃ =
      (Cofan.mk T fun i =>
              Fin.cases f₁ (fun i => Sigma.ι (fun j => (Discrete.functor F').obj { as := j.succ }) i ≫ f₂) i).ι.app
        j

Tactic:
intro ⟨j⟩

Result:
case refine_2.uniq
C : Type u
inst✝² : Category.{v, u} C
n : ℕ
f : Fin (n + 1) → C
c₁ : Cofan fun i => f i.succ
c₂ : BinaryCofan (f 0) c₁.pt
t₁ : IsVanKampenColimit c₁
t₂ : IsVanKampenColimit c₂
inst✝¹ : ∀ {Z : C} (i : Z ⟶ c₂.pt), HasPullback c₂.inr i
inst✝ : HasFiniteCoproducts C
j✝ : Fin (n + 1)
F' : Fin (n + 1) → C
c : Cocone (Discrete.functor F')
α : Discrete.functor F' ⟶ Discrete.functor f
i : c.pt ⟶ (extendCofan c₁ c₂).pt
e : α ≫ (extendCofan c₁ c₂).ι = c.ι ≫ (Functor.const (Discrete (Fin (n + 1)))).map i
hα : NatTrans.Equifibered α
Hc : IsColimit c
T : C
f₁ : F' 0 ⟶ T
f₂ : (∐ fun j => (Discrete.functor F').obj { as := j.succ }) ⟶ T
f₃ : (BinaryCofan.mk (c.ι.app { as := 0 }) (Sigma.desc fun b => c.ι.app { as := b.succ })).pt ⟶ T
m₁ : c.ι.app { as := 0 } ≫ f₃ = f₁
m₂ : (Sigma.desc fun b => c.ι.app { as := b.succ }) ≫ f₃ = f₂
j : Fin (n + 1)
⊢ c.ι.app { as := j } ≫ f₃ =
    (Cofan.mk T fun i =>
            Fin.cases f₁ (fun i => Sigma.ι (fun j => (Discrete.functor F').obj { as := j.succ }) i ≫ f₂) i).ι.app
      { as := j }

Proof state:
case refine_2.hd₁
C : Type u
inst✝² : Category.{v, u} C
n : ℕ
f : Fin (n + 1) → C
c₁ : Cofan fun i => f i.succ
c₂ : BinaryCofan (f 0) c₁.pt
t₁ : IsVanKampenColimit c₁
t₂ : IsVanKampenColimit c₂
inst✝¹ : ∀ {Z : C} (i : Z ⟶ c₂.pt), HasPullback c₂.inr i
inst✝ : HasFiniteCoproducts C
j : Fin (n + 1)
F' : Fin (n + 1) → C
c : Cocone (Discrete.functor F')
α : Discrete.functor F' ⟶ Discrete.functor f
i : c.pt ⟶ (extendCofan c₁ c₂).pt
e : α ≫ (extendCofan c₁ c₂).ι = c.ι ≫ (Functor.const (Discrete (Fin (n + 1)))).map i
hα : NatTrans.Equifibered α
Hc : IsColimit c
T : C
f₁ : F' 0 ⟶ T
f₂ : (∐ fun j => (Discrete.functor F').obj { as := j.succ }) ⟶ T
⊢ (BinaryCofan.mk (c.ι.app { as := 0 }) (Sigma.desc fun b => c.ι.app { as := b.succ })).inl ≫
      Hc.desc
        (Cofan.mk T fun i =>
          Fin.cases f₁ (fun i => Sigma.ι (fun j => (Discrete.functor F').obj { as := j.succ }) i ≫ f₂) i) =
    f₁

Tactic:
simp only [Discrete.functor_obj, pair_obj_left, BinaryCofan.mk_pt, Functor.const_obj_obj,
  BinaryCofan.ι_app_left, BinaryCofan.mk_inl, IsColimit.fac, Cofan.mk_pt, Cofan.mk_ι_app,
  Fin.cases_zero]

Result:
no goals