-- Mathlib/CategoryTheory/Triangulated/Pretriangulated.lean
/-- A product of distinguished triangles is distinguished -/
lemma productTriangle_distinguished {J : Type*} (T : J → Triangle C)
    (hT : ∀ j, T j ∈ distTriang C)
    [HasProduct (fun j => (T j).obj₁)] [HasProduct (fun j => (T j).obj₂)]
    [HasProduct (fun j => (T j).obj₃)] [HasProduct (fun j => (T j).obj₁⟦(1 : ℤ)⟧)] :
    productTriangle T ∈ distTriang C

Proof state:
case intro.intro.intro.refine_2.intro
C : Type u
inst✝⁸ : Category.{v, u} C
inst✝⁷ : HasZeroObject C
inst✝⁶ : HasShift C ℤ
inst✝⁵ : Preadditive C
inst✝⁴ : ∀ (n : ℤ), (shiftFunctor C n).Additive
hC : Pretriangulated C
J : Type u_1
T : J → Triangle C
hT : ∀ (j : J), T j ∈ distinguishedTriangles
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
f₁ : (∏ᶜ fun j => (T j).obj₁) ⟶ ∏ᶜ fun j => (T j).obj₂ := Limits.Pi.map fun j => (T j).mor₁
Z : C
f₂ : (∏ᶜ fun j => (T j).obj₂) ⟶ Z
f₃ : Z ⟶ (shiftFunctor C 1).obj (∏ᶜ fun j => (T j).obj₁)
T' : Triangle C := Triangle.mk f₁ f₂ f₃
hT' : T' ∈ distinguishedTriangles
φ : (j : J) → T' ⟶ T j :=
  fun j =>
    completeDistinguishedTriangleMorphism T' (T j) hT' ⋯ (Pi.π (fun j => (T j).obj₁) j) (Pi.π (fun j => (T j).obj₂) j) ⋯
φ' : T' ⟶ productTriangle T := productTriangle.lift T φ
h₁ : φ'.hom₁ = 𝟙 T'.obj₁
h₂ : φ'.hom₂ = 𝟙 T'.obj₂
this✝ : IsIso φ'.hom₁
this : IsIso φ'.hom₂
A : C
a : A ⟶ (productTriangle T).obj₃
a' : A ⟶ Z
ha' : a' ≫ T'.mor₃ = a ≫ (productTriangle T).mor₃
⊢ ∃ a_1, (fun x => x ≫ φ'.hom₃) a_1 = a

Tactic:
have ha'' := fun (j : J) => (T j).coyoneda_exact₃ (hT j) ((a - a' ≫ φ'.hom₃) ≫ Pi.π _ j) (by
  simp only [sub_comp, assoc]
  erw [← (productTriangle.π T j).comm₃]
  rw [← φ'.comm₃_assoc]
  rw [reassoc_of% ha', sub_eq_zero, h₁, Functor.map_id, id_comp])

Result:
case intro.intro.intro.refine_2.intro
C : Type u
inst✝⁸ : Category.{v, u} C
inst✝⁷ : HasZeroObject C
inst✝⁶ : HasShift C ℤ
inst✝⁵ : Preadditive C
inst✝⁴ : ∀ (n : ℤ), (shiftFunctor C n).Additive
hC : Pretriangulated C
J : Type u_1
T : J → Triangle C
hT : ∀ (j : J), T j ∈ distinguishedTriangles
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
f₁ : (∏ᶜ fun j => (T j).obj₁) ⟶ ∏ᶜ fun j => (T j).obj₂ := Limits.Pi.map fun j => (T j).mor₁
Z : C
f₂ : (∏ᶜ fun j => (T j).obj₂) ⟶ Z
f₃ : Z ⟶ (shiftFunctor C 1).obj (∏ᶜ fun j => (T j).obj₁)
T' : Triangle C := Triangle.mk f₁ f₂ f₃
hT' : T' ∈ distinguishedTriangles
φ : (j : J) → T' ⟶ T j :=
  fun j =>
    completeDistinguishedTriangleMorphism T' (T j) hT' ⋯ (Pi.π (fun j => (T j).obj₁) j) (Pi.π (fun j => (T j).obj₂) j) ⋯
φ' : T' ⟶ productTriangle T := productTriangle.lift T φ
h₁ : φ'.hom₁ = 𝟙 T'.obj₁
h₂ : φ'.hom₂ = 𝟙 T'.obj₂
this✝ : IsIso φ'.hom₁
this : IsIso φ'.hom₂
A : C
a : A ⟶ (productTriangle T).obj₃
a' : A ⟶ Z
ha' : a' ≫ T'.mor₃ = a ≫ (productTriangle T).mor₃
ha'' : ∀ (j : J), ∃ g, (a - a' ≫ φ'.hom₃) ≫ Pi.π (fun j => (T j).obj₃) j = g ≫ (T j).mor₂
⊢ ∃ a_1, (fun x => x ≫ φ'.hom₃) a_1 = a

Proof state:
case intro.intro.intro
C : Type u
inst✝⁸ : Category.{v, u} C
inst✝⁷ : HasZeroObject C
inst✝⁶ : HasShift C ℤ
inst✝⁵ : Preadditive C
inst✝⁴ : ∀ (n : ℤ), (shiftFunctor C n).Additive
hC : Pretriangulated C
J : Type u_1
T : J → Triangle C
hT : ∀ (j : J), T j ∈ distinguishedTriangles
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
f₁ : (∏ᶜ fun j => (T j).obj₁) ⟶ ∏ᶜ fun j => (T j).obj₂ := Limits.Pi.map fun j => (T j).mor₁
Z : C
f₂ : (∏ᶜ fun j => (T j).obj₂) ⟶ Z
f₃ : Z ⟶ (shiftFunctor C 1).obj (∏ᶜ fun j => (T j).obj₁)
T' : Triangle C := Triangle.mk f₁ f₂ f₃
hT' : T' ∈ distinguishedTriangles
φ : (j : J) → T' ⟶ T j :=
  fun j =>
    completeDistinguishedTriangleMorphism T' (T j) hT' ⋯ (Pi.π (fun j => (T j).obj₁) j) (Pi.π (fun j => (T j).obj₂) j) ⋯
φ' : T' ⟶ productTriangle T := productTriangle.lift T φ
h₁ : φ'.hom₁ = 𝟙 T'.obj₁
h₂ : φ'.hom₂ = 𝟙 T'.obj₂
this✝ : IsIso φ'.hom₁
this : IsIso φ'.hom₂
⊢ productTriangle T ∈ distinguishedTriangles

Tactic:
suffices IsIso φ'.hom₃ by
  have : IsIso φ' := by
    apply Triangle.isIso_of_isIsos
    all_goals infer_instance
  exact isomorphic_distinguished _ hT' _ (asIso φ').symm

Result:
case intro.intro.intro
C : Type u
inst✝⁸ : Category.{v, u} C
inst✝⁷ : HasZeroObject C
inst✝⁶ : HasShift C ℤ
inst✝⁵ : Preadditive C
inst✝⁴ : ∀ (n : ℤ), (shiftFunctor C n).Additive
hC : Pretriangulated C
J : Type u_1
T : J → Triangle C
hT : ∀ (j : J), T j ∈ distinguishedTriangles
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
f₁ : (∏ᶜ fun j => (T j).obj₁) ⟶ ∏ᶜ fun j => (T j).obj₂ := Limits.Pi.map fun j => (T j).mor₁
Z : C
f₂ : (∏ᶜ fun j => (T j).obj₂) ⟶ Z
f₃ : Z ⟶ (shiftFunctor C 1).obj (∏ᶜ fun j => (T j).obj₁)
T' : Triangle C := Triangle.mk f₁ f₂ f₃
hT' : T' ∈ distinguishedTriangles
φ : (j : J) → T' ⟶ T j :=
  fun j =>
    completeDistinguishedTriangleMorphism T' (T j) hT' ⋯ (Pi.π (fun j => (T j).obj₁) j) (Pi.π (fun j => (T j).obj₂) j) ⋯
φ' : T' ⟶ productTriangle T := productTriangle.lift T φ
h₁ : φ'.hom₁ = 𝟙 T'.obj₁
h₂ : φ'.hom₂ = 𝟙 T'.obj₂
this✝ : IsIso φ'.hom₁
this : IsIso φ'.hom₂
⊢ IsIso φ'.hom₃

Proof state:
case intro.intro.intro
C : Type u
inst✝⁸ : Category.{v, u} C
inst✝⁷ : HasZeroObject C
inst✝⁶ : HasShift C ℤ
inst✝⁵ : Preadditive C
inst✝⁴ : ∀ (n : ℤ), (shiftFunctor C n).Additive
hC : Pretriangulated C
J : Type u_1
T : J → Triangle C
hT : ∀ (j : J), T j ∈ distinguishedTriangles
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
f₁ : (∏ᶜ fun j => (T j).obj₁) ⟶ ∏ᶜ fun j => (T j).obj₂ := Limits.Pi.map fun j => (T j).mor₁
Z : C
f₂ : (∏ᶜ fun j => (T j).obj₂) ⟶ Z
f₃ : Z ⟶ (shiftFunctor C 1).obj (∏ᶜ fun j => (T j).obj₁)
hT' : Triangle.mk f₁ f₂ f₃ ∈ distinguishedTriangles
⊢ productTriangle T ∈ distinguishedTriangles

Tactic:
let T' := Triangle.mk f₁ f₂ f₃

Result:
case intro.intro.intro
C : Type u
inst✝⁸ : Category.{v, u} C
inst✝⁷ : HasZeroObject C
inst✝⁶ : HasShift C ℤ
inst✝⁵ : Preadditive C
inst✝⁴ : ∀ (n : ℤ), (shiftFunctor C n).Additive
hC : Pretriangulated C
J : Type u_1
T : J → Triangle C
hT : ∀ (j : J), T j ∈ distinguishedTriangles
inst✝³ : HasProduct fun j => (T j).obj₁
inst✝² : HasProduct fun j => (T j).obj₂
inst✝¹ : HasProduct fun j => (T j).obj₃
inst✝ : HasProduct fun j => (shiftFunctor C 1).obj (T j).obj₁
f₁ : (∏ᶜ fun j => (T j).obj₁) ⟶ ∏ᶜ fun j => (T j).obj₂ := Limits.Pi.map fun j => (T j).mor₁
Z : C
f₂ : (∏ᶜ fun j => (T j).obj₂) ⟶ Z
f₃ : Z ⟶ (shiftFunctor C 1).obj (∏ᶜ fun j => (T j).obj₁)
hT' : Triangle.mk f₁ f₂ f₃ ∈ distinguishedTriangles
T' : Triangle C := Triangle.mk f₁ f₂ f₃
⊢ productTriangle T ∈ distinguishedTriangles