-- Mathlib/CategoryTheory/Limits/VanKampen.lean
theorem isPullback_of_cofan_isVanKampen [HasInitial C] {ι : Type*} {X : ι → C}
    {c : Cofan X} (hc : IsVanKampenColimit c) (i j : ι) [DecidableEq ι] :
    IsPullback (P := (if j = i then X i else ⊥_ C))
      (if h : j = i then eqToHom (if_pos h) else eqToHom (if_neg h) ≫ initial.to (X i))
      (if h : j = i then eqToHom ((if_pos h).trans (congr_arg X h.symm))
        else eqToHom (if_neg h) ≫ initial.to (X j))
      (Cofan.inj c i) (Cofan.inj c j)

Proof state:
case refine_2.refine_1.isFalse
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j✝ : ι
inst✝ : DecidableEq ι
t : Cofan fun k => if k = i then X i else ⊥_ C
j : ι
h✝ : ¬j = i
⊢ (eqToHom ⋯ ≫ initial.to (X i)) ≫ eqToHom ⋯ ≫ t.inj i = t.inj j

Tactic:
rw [Category.assoc, ← IsIso.eq_inv_comp]

Result:
case refine_2.refine_1.isFalse
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j✝ : ι
inst✝ : DecidableEq ι
t : Cofan fun k => if k = i then X i else ⊥_ C
j : ι
h✝ : ¬j = i
⊢ initial.to (X i) ≫ eqToHom ⋯ ≫ t.inj i = inv (eqToHom ⋯) ≫ t.inj j

Proof state:
case refine_1.w.h.mk.isTrue
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
k : ι
h✝ : k = i
⊢ eqToHom ⋯ ≫ c.ι.app { as := k } = eqToHom ⋯ ≫ c.inj i

Tactic:
subst ‹k = i›

Result:
case refine_1.w.h.mk.isTrue
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
j : ι
inst✝ : DecidableEq ι
k : ι
⊢ eqToHom ⋯ ≫ c.ι.app { as := k } = eqToHom ⋯ ≫ c.inj k

Proof state:
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
⊢ IsPullback (if h : j = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X i))
    (if h : j = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X j)) (c.inj i) (c.inj j)

Tactic:
refine (hc (Cofan.mk (X i) (f := fun k ↦ if k = i then X i else ⊥_ C)
  (fun k ↦ if h : k = i then (eqToHom <| if_pos h) else (eqToHom <| if_neg h) ≫ initial.to _))
  (Discrete.natTrans (fun k ↦ if h : k.1 = i then (eqToHom <| (if_pos h).trans
    (congr_arg X h.symm)) else (eqToHom <| if_neg h) ≫ initial.to _))
  (c.inj i) ?_ (NatTrans.equifibered_of_discrete _)).mp ⟨?_⟩ ⟨j⟩

Result:
case refine_1
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
⊢ (Discrete.natTrans fun k => if h : k.as = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to ((Discrete.functor X).obj k)) ≫
      c.ι =
    (Cofan.mk (X i) fun k => if h : k = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X i)).ι ≫
      (Functor.const (Discrete ι)).map (c.inj i)

case refine_2
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
⊢ IsColimit (Cofan.mk (X i) fun k => if h : k = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X i))

Proof state:
case refine_1.w.h.mk.isFalse
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
k : ι
h✝ : ¬k = i
⊢ (eqToHom ⋯ ≫ initial.to (X k)) ≫ c.ι.app { as := k } = (eqToHom ⋯ ≫ initial.to (X i)) ≫ c.inj i

Tactic:
simp

Result:
no goals

Proof state:
case refine_1.w.h.mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
k : ι
⊢ (if h : k = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X k)) ≫ c.ι.app { as := k } =
    (if h : k = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X i)) ≫ c.inj i

Tactic:
split

Result:
case refine_1.w.h.mk.isTrue
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
k : ι
h✝ : k = i
⊢ eqToHom ⋯ ≫ c.ι.app { as := k } = eqToHom ⋯ ≫ c.inj i

case refine_1.w.h.mk.isFalse
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
k : ι
h✝ : ¬k = i
⊢ (eqToHom ⋯ ≫ initial.to (X k)) ≫ c.ι.app { as := k } = (eqToHom ⋯ ≫ initial.to (X i)) ≫ c.inj i

Proof state:
case refine_2.refine_1.isTrue
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j✝ : ι
inst✝ : DecidableEq ι
t : Cofan fun k => if k = i then X i else ⊥_ C
j : ι
h✝ : j = i
⊢ eqToHom ⋯ ≫ eqToHom ⋯ ≫ t.inj i = t.inj j

Tactic:
subst ‹j = i›

Result:
case refine_2.refine_1.isTrue
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
j✝ : ι
inst✝ : DecidableEq ι
j : ι
t : Cofan fun k => if k = j then X j else ⊥_ C
⊢ eqToHom ⋯ ≫ eqToHom ⋯ ≫ t.inj j = t.inj j

Proof state:
case refine_1
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
⊢ (Discrete.natTrans fun k => if h : k.as = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to ((Discrete.functor X).obj k)) ≫
      c.ι =
    (Cofan.mk (X i) fun k => if h : k = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X i)).ι ≫
      (Functor.const (Discrete ι)).map (c.inj i)

Tactic:
ext ⟨k⟩

Result:
case refine_1.w.h.mk
C : Type u
inst✝² : Category.{v, u} C
inst✝¹ : HasInitial C
ι : Type u_3
X : ι → C
c : Cofan X
hc : IsVanKampenColimit c
i j : ι
inst✝ : DecidableEq ι
k : ι
⊢ ((Discrete.natTrans fun k =>
            if h : k.as = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to ((Discrete.functor X).obj k)) ≫
          c.ι).app
      { as := k } =
    ((Cofan.mk (X i) fun k => if h : k = i then eqToHom ⋯ else eqToHom ⋯ ≫ initial.to (X i)).ι ≫
          (Functor.const (Discrete ι)).map (c.inj i)).app
      { as := k }