import Mathlib

inductive Color
| Red
| Black
deriving Inhabited, BEq

inductive Node
| Empty : Node
| Tree  (color : Color) (val : Int) (left : Node) (right : Node) : Node
deriving Inhabited

def view (t : Node) : Set Int :=
  match t with
  | Node.Empty => ∅
  | Node.Tree _ v l r => view l ∪ view r ∪ {v}

def is_red (t : Node) : Bool :=
  match t with
  | Node.Tree Color.Red _ _ _ => true
  | _ => false

def get_color (t : Node) : Color :=
  match t with
  | Node.Tree c _ _ _ => c
  | Node.Empty => Color.Black -- Empty nodes are black

def is_bst (t : Node) : Prop :=
  match t with
  | Node.Empty => True
  | Node.Tree _ v l r =>
    (∀ x ∈ view l, x < v) ∧
    is_bst l ∧
    (∀ x ∈ view r, x > v) ∧
    is_bst r

-- Black Height: Returns -1 if invalid
def black_height (t : Node) : Int :=
  match t with
  | Node.Empty => 1
  | Node.Tree c _ l r =>
    let lh := black_height l
    let rh := black_height r
    if lh ≠ -1 ∧ rh ≠ -1 ∧ lh = rh then
      if c == Color.Black then lh + 1 else lh
    else
      -1

def get_left (t : Node) : Option Node :=
  match t with | Node.Tree _ _ l _ => some l | _ => none

def get_right (t : Node) : Option Node :=
  match t with | Node.Tree _ _ _ r => some r | _ => none

def is_not_empty (t : Node) : Prop :=
  match t with | Node.Empty => False | _ => True

-- Precondition definitions
@[reducible, simp]
def rotate_left_precond (t : Node) : Prop :=
  -- !benchmark @start precond
  match t with
  | Node.Tree _ _ _ r =>
    -- Right child exists and is Red.
    -- (Dafny spec says Right is Red. Node itself can be any color).
    is_red r
  | _ => False
  -- !benchmark @end precond

-- !benchmark @start auxcode
-- !benchmark @end auxcode

-- Main function definition
def rotate_left (t : Node) 
    (h_precond : rotate_left_precond t) : Node :=
  -- !benchmark @start code
  sorry
  -- !benchmark @end code

-- Postcondition definitions
@[reducible, simp]
def rotate_left_postcond (t : Node) (result : Node)
    (_ : rotate_left_precond t) : Prop :=
  -- !benchmark @start postcond
  view result = view t ∧
  is_bst t → is_bst result ∧
  match result, t with
  | Node.Tree c' _ l' _, Node.Tree c _ _ r =>
      -- New root color matches old root color
      c' = c ∧
      -- New left child matches old root and is RED
      (match l' with
       | Node.Tree Color.Red _ _ _ => True
       | _ => False) ∧
      -- Black height preservation
      (black_height t ≠ -1 → black_height result = black_height t)
  | _, _ => False
  -- !benchmark @end postcond

-- !benchmark @start lemma
-- !benchmark @end lemma

-- Proof content
theorem rotate_left_postcond_satisfied (t : Node)
    (h_precond : rotate_left_precond t) :
    rotate_left_postcond t (rotate_left t h_precond) h_precond := by
  -- !benchmark @start proof
  sorry
  -- !benchmark @end proof