import Mathlib

variable {m n : Type*} [Fintype m] [Fintype n] [DecidableEq m] [DecidableEq n]

/--
If the block matrix `fromBlocks A B C D : Matrix (m ⊕ n) (m ⊕ n) R` is orthogonal
and `I - A` is invertible, then the Schur-type expression
`D + C * (I - A)⁻¹ * B : Matrix n n R` is orthogonal.

Here “orthogonal” is expressed as membership in `Matrix.orthogonalGroup`.
-/
theorem orthogonal_of_block
    (A : Matrix m m ℝ) (B : Matrix m n ℝ)
    (C : Matrix n m ℝ) (D : Matrix n n ℝ)
    (hU : Matrix.fromBlocks A B C D ∈ Matrix.orthogonalGroup (m ⊕ n) ℝ)
    (hInv : IsUnit ((1 : Matrix m m ℝ) - A)) :
    D + C * ((1 : Matrix m m ℝ) - A)⁻¹ * B ∈ Matrix.orthogonalGroup n ℝ := by
  obtain ⟨ a, ha ⟩ := hInv.exists_left_inv;
  -- Using the fact that $U$ is orthogonal, we can derive the necessary equations for $A$, $B$, $C$, and $D$.
  have h_eq : A.transpose * A + C.transpose * C = 1 ∧ A.transpose * B + C.transpose * D = 0 ∧ B.transpose * A + D.transpose * C = 0 ∧ B.transpose * B + D.transpose * D = 1 := by
    have h_eq : (Matrix.fromBlocks A B C D).transpose * (Matrix.fromBlocks A B C D) = 1 := by
      convert hU.1 using 1;
    -- By definition of matrix multiplication, we can expand the product of the transpose of the block matrix and the original block matrix.
    have h_expand : (Matrix.fromBlocks A B C D).transpose * (Matrix.fromBlocks A B C D) = Matrix.fromBlocks (A.transpose * A + C.transpose * C) (A.transpose * B + C.transpose * D) (B.transpose * A + D.transpose * C) (B.transpose * B + D.transpose * D) := by
      ext i j; simp +decide [ Matrix.mul_apply, Matrix.transpose_apply, Matrix.fromBlocks ] ;
      rcases i with ( i | i ) <;> rcases j with ( j | j ) <;> simp +decide [ Matrix.mul_apply, Matrix.add_apply ];
    simp_all +decide [ ← Matrix.ext_iff, Fin.sum_univ_succ ];
    simp +decide [ Matrix.one_apply ];
  -- Now consider the expression $(D + C * (1 - A)⁻¹ * B)^T * (D + C * (1 - A)⁻¹ * B)$.
  have h_schur_simplified : (D + C * a * B).transpose * (D + C * a * B) = 1 := by
    -- Substitute the given equations into the expanded product.
    have h_subst : D.transpose * D + D.transpose * C * a * B + B.transpose * a.transpose * C.transpose * D + B.transpose * a.transpose * C.transpose * C * a * B = (1 - B.transpose * B) + (-B.transpose * A) * a * B + B.transpose * a.transpose * (-A.transpose * B) + B.transpose * a.transpose * (1 - A.transpose * A) * a * B := by
      simp_all +decide [ ← eq_sub_iff_add_eq', mul_assoc, Matrix.mul_sub, Matrix.sub_mul ];
      simp_all +decide [ Matrix.mul_assoc, ← Matrix.mul_sub ] ; abel_nf;
      simp +decide [ Matrix.add_mul, Matrix.mul_assoc ];
    -- Using the fact that $a * (1 - A) = 1$, we can simplify the expression further.
    have h_simplify : a.transpose * A.transpose = a.transpose - 1 := by
      apply_fun Matrix.transpose at ha;
      norm_num +zetaDelta at *;
      rw [ ← Matrix.mul_eq_one_comm ] at ha;
      rw [ ← ha, mul_sub, mul_one ];
      abel1;
    simp_all +decide [ Matrix.mul_assoc, sub_mul, mul_sub ];
    simp_all +decide [ Matrix.add_mul, Matrix.mul_add, ← Matrix.mul_assoc ];
    simp_all +decide [ mul_assoc, sub_mul, mul_sub ];
    -- Substitute $A * a = a - 1$ into the expression.
    have h_Aa : A * a = a - 1 := by
      rw [ ← Matrix.transpose_inj ] ; simp_all +decide [ Matrix.mul_assoc, Matrix.transpose_mul ];
    simp_all +decide [ ← Matrix.mul_assoc, ← eq_sub_iff_add_eq' ];
    rw [ show B.transpose * A * a * B = B.transpose * ( A * a ) * B by simp +decide only [ Matrix.mul_assoc ] ] ; rw [ h_Aa ] ; simp +decide [ Matrix.mul_assoc, Matrix.sub_mul, Matrix.mul_sub ] ; abel_nf;
  rw [ Matrix.inv_eq_left_inv ha ];
  exact Matrix.mem_unitaryGroup_iff'.mpr h_schur_simplified
