#!/bin/bash
set -euo pipefail

# POST-CHECK: Architecture — Clean Architecture Layer Isolation
# A1-A8: Layer boundary enforcement, DTO usage, handoff compliance

FAIL=false

# POST-CHECK A1: Domain must not import other layers (BLOCKING)
DOMAIN_FILES=$(find src/ -path "*/Domain/*" -name "*.cs" 2>/dev/null)
if [ -n "$DOMAIN_FILES" ]; then
  BAD_IMPORTS=$(grep -Pn 'using\s+[\w.]*\.(Application|Infrastructure|Api)[\w.]*;' $DOMAIN_FILES 2>/dev/null || true)
  if [ -n "$BAD_IMPORTS" ]; then
    echo "BLOCKING: Domain layer imports Application/Infrastructure/Api — violates Clean Architecture"
    echo "Domain is the core, it must not depend on any other layer"
    echo "$BAD_IMPORTS"
    echo "Fix: Move shared types to Domain or remove the dependency"
    FAIL=true
  fi
fi

# POST-CHECK A2: Application must not import Infrastructure or Api (BLOCKING)
APP_FILES=$(find src/ -path "*/Application/*" -name "*.cs" 2>/dev/null)
if [ -n "$APP_FILES" ]; then
  BAD_IMPORTS=$(grep -Pn 'using\s+[\w.]*\.(Infrastructure|Api)[\w.]*;' $APP_FILES 2>/dev/null || true)
  if [ -n "$BAD_IMPORTS" ]; then
    echo "BLOCKING: Application layer imports Infrastructure/Api — violates Clean Architecture"
    echo "Application defines interfaces, Infrastructure implements them"
    echo "$BAD_IMPORTS"
    echo "Fix: Define an interface in Application and implement it in Infrastructure"
    FAIL=true
  fi
fi

# POST-CHECK A3: Controllers must not inject DbContext (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  BAD_DBCONTEXT=$(grep -Pn 'private\s+readonly\s+\w*DbContext|DbContext\s+\w+[,)]' $CTRL_FILES 2>/dev/null || true)
  if [ -n "$BAD_DBCONTEXT" ]; then
    echo "BLOCKING: Controller injects DbContext directly — violates Clean Architecture"
    echo "Controllers must use Application services, not access the database directly"
    echo "$BAD_DBCONTEXT"
    echo "Fix: Create an Application service with the required business logic and inject it instead"
    FAIL=true
  fi
fi

# POST-CHECK A4: API must return DTOs, not Domain entities (WARNING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
ENTITY_FILES=$(find src/ -path "*/Domain/Entities/*" -name "*.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ] && [ -n "$ENTITY_FILES" ]; then
  ENTITY_NAMES=$(grep -ohP 'public\s+class\s+(\w+)\s*:' $ENTITY_FILES 2>/dev/null | grep -oP '\w+(?=\s*:)' | grep -v '^public$' | sort -u || true)
  for ENTITY in $ENTITY_NAMES; do
    BAD_RETURN=$(grep -Pn "ActionResult<$ENTITY>|ActionResult<IEnumerable<$ENTITY>>|ActionResult<List<$ENTITY>>" $CTRL_FILES 2>/dev/null || true)
    if [ -n "$BAD_RETURN" ]; then
      echo "WARNING: Controller returns Domain entity '$ENTITY' instead of a DTO"
      echo "$BAD_RETURN"
      echo "Fix: Return ${ENTITY}ResponseDto instead of $ENTITY"
    fi
  done
fi

# POST-CHECK A5: Service interfaces in Application, implementations in Infrastructure (WARNING)
APP_SERVICES=$(find src/ -path "*/Application/*" -name "*Service.cs" ! -name "I*Service.cs" 2>/dev/null)
if [ -n "$APP_SERVICES" ]; then
  for f in $APP_SERVICES; do
    if grep -q 'public class.*Service' "$f" 2>/dev/null; then
      echo "WARNING: Service implementation found in Application layer: $f"
      echo "Fix: Move implementation to Infrastructure/Services/. Application should only contain interfaces."
    fi
  done
fi

DOMAIN_INTERFACES=$(find src/ -path "*/Domain/*" -name "I*Service.cs" 2>/dev/null)
API_INTERFACES=$(find src/ -path "*/Api/*" -name "I*Service.cs" 2>/dev/null)
for f in $DOMAIN_INTERFACES $API_INTERFACES; do
  if [ -n "$f" ] && grep -q 'public interface.*Service' "$f" 2>/dev/null; then
    echo "WARNING: Service interface found outside Application layer: $f"
    echo "Fix: Move to Application/Interfaces/"
  fi
done

# POST-CHECK A6: No EF Core attributes in Domain entities (BLOCKING)
DOMAIN_FILES=$(find src/ -path "*/Domain/*" -name "*.cs" 2>/dev/null)
if [ -n "$DOMAIN_FILES" ]; then
  BAD_EF=$(grep -Pn '\[Table\(|\[Column\(|\[Index\(|using\s+Microsoft\.EntityFrameworkCore' $DOMAIN_FILES 2>/dev/null || true)
  if [ -n "$BAD_EF" ]; then
    echo "BLOCKING: EF Core attributes or using directives found in Domain layer"
    echo "Domain entities must be persistence-ignorant — EF configuration belongs in Infrastructure"
    echo "$BAD_EF"
    echo "Fix: Move [Table], [Column], [Index] to IEntityTypeConfiguration<T> in Infrastructure/Persistence/Configurations/"
    FAIL=true
  fi
fi

# POST-CHECK A7: No direct repository usage in controllers (WARNING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  BAD_REPO=$(grep -Pn 'IRepository<|IGenericRepository<|private\s+readonly\s+IRepository|private\s+readonly\s+IGenericRepository' $CTRL_FILES 2>/dev/null || true)
  if [ -n "$BAD_REPO" ]; then
    echo "WARNING: Controller injects repository directly — should use Application services"
    echo "$BAD_REPO"
    echo "Fix: Controllers should depend on Application services (I*Service), not repositories"
  fi
fi

# POST-CHECK A8: API endpoints must match handoff apiEndpointSummary (BLOCKING)
PRD_FILE=".ralph/prd.json"
if [ ! -f "$PRD_FILE" ]; then
  if [ -f ".ralph/modules-queue.json" ]; then
    PRD_FILE=$(cat .ralph/modules-queue.json | grep -o '"prdFile":"[^"]*"' | tail -1 | cut -d'"' -f4)
  fi
fi

if [ -f "$PRD_FILE" ]; then
  OPERATIONS=$(cat "$PRD_FILE" | grep -o '"operation"\s*:\s*"[^"]*"' | cut -d'"' -f4 2>/dev/null || true)

  if [ -n "$OPERATIONS" ]; then
    CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
    MISSING_OPS=""
    TOTAL_OPS=0
    FOUND_OPS=0

    for op in $OPERATIONS; do
      TOTAL_OPS=$((TOTAL_OPS + 1))
      FOUND=false
      if [ -n "$CTRL_FILES" ]; then
        for f in $CTRL_FILES; do
          if grep -q "$op" "$f" 2>/dev/null; then
            FOUND=true
            break
          fi
        done
      fi
      if [ "$FOUND" = true ]; then
        FOUND_OPS=$((FOUND_OPS + 1))
      else
        MISSING_OPS="$MISSING_OPS $op"
      fi
    done

    if [ -n "$MISSING_OPS" ]; then
      echo "BLOCKING: API endpoints missing from controllers (handoff contract violation)"
      echo "Found: $FOUND_OPS/$TOTAL_OPS operations"
      echo "Missing operations:$MISSING_OPS"
      echo "Fix: Implement missing endpoints in the appropriate Controller"
      FAIL=true
    fi
  fi
fi

if [ "$FAIL" = true ]; then
  exit 1
fi
