#!/bin/bash
set -euo pipefail

# POST-CHECK: Seed Data — Navigation, Roles, Permissions
# C1-C2, C10, C15-C23, C32-C35, C44-C48, C53: Navigation completeness, role matrix, idempotency, translations

FAIL=false

# POST-CHECK C1: Navigation routes must be full paths starting with /
SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
if [ -n "$SEED_FILES" ]; then
  BAD_ROUTES=$(grep -Pn 'NavigationApplication\.Create\(|NavigationModule\.Create\(|NavigationSection\.Create\(|NavigationResource\.Create\(' $SEED_FILES | grep -v '"/[a-z]' || true)
  if [ -n "$BAD_ROUTES" ]; then
    echo "WARNING: Navigation routes must be full paths starting with /"
    echo "$BAD_ROUTES"
    echo "Expected: \"/human-resources\" NOT \"humanresources\""
  fi
fi

# POST-CHECK C2: Seed data must not use deterministic/sequential/fixed GUIDs
SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
if [ -n "$SEED_FILES" ]; then
  BAD_GUIDS=$(grep -Pn 'GenerateDeterministicGuid|GenerateGuid\(int|11111111-1111-1111-1111-' $SEED_FILES 2>/dev/null || true)
  if [ -n "$BAD_GUIDS" ]; then
    echo "WARNING: Seed data must use Guid.NewGuid(), not deterministic/sequential/fixed GUIDs"
    echo "$BAD_GUIDS"
  fi
fi

# POST-CHECK C10: Routes seed data must match frontend application routes
SEED_ROUTES=$(grep -Poh 'Route\s*=\s*"([^"]+)"' $(find src/ -path "*/Seeding/Data/*" -name "*NavigationSeedData.cs" 2>/dev/null) 2>/dev/null | grep -oP '"[^"]+"' | tr -d '"' | sort -u || true)
APP_TSX=$(find src/ -name "App.tsx" -not -path "*/node_modules/*" 2>/dev/null | head -1)
if [ -n "$APP_TSX" ] && [ -n "$SEED_ROUTES" ]; then
  FRONTEND_PATHS=$(grep -oP "path:\s*'([^']+)'" "$APP_TSX" | grep -oP "'[^']+'" | tr -d "'" | sort -u || true)
  if [ -n "$FRONTEND_PATHS" ]; then
    MISMATCH_FOUND=false
    for SEED_ROUTE in $SEED_ROUTES; do
      DEPTH=$(echo "$SEED_ROUTE" | tr '/' '\n' | grep -c '.')
      if [ "$DEPTH" -lt 3 ]; then continue; fi
      SEED_SUFFIX=$(echo "$SEED_ROUTE" | sed 's|^/[^/]*/||')
      SEED_NORM=$(echo "$SEED_SUFFIX" | tr '[:upper:]' '[:lower:]' | tr -d '-')
      MATCH_FOUND=false
      for FE_PATH in $FRONTEND_PATHS; do
        if echo "$FE_PATH" | grep -qP '/list$'; then
          echo "WARNING: Frontend route ends with /list — should use index route instead: $FE_PATH"
        fi
        FE_BASE=$(echo "$FE_PATH" | sed 's|/list$||;s|/new$||;s|/:id.*||;s|/create$||')
        FE_NORM=$(echo "$FE_BASE" | tr '[:upper:]' '[:lower:]' | tr -d '-')
        if [ "$SEED_NORM" = "$FE_NORM" ]; then
          MATCH_FOUND=true
          break
        fi
      done
      if [ "$MATCH_FOUND" = false ]; then
        echo "CRITICAL: Seed data route has no matching frontend route: $SEED_ROUTE"
        MISMATCH_FOUND=true
      fi
    done
    if [ "$MISMATCH_FOUND" = true ]; then
      echo "Fix: Ensure every NavigationSeedData route has a corresponding PageRegistry.register() entry in componentRegistry.generated.ts (or route entry in App.tsx for legacy projects)"
      FAIL=true
    fi
  fi
fi

# POST-CHECK C15: RolePermission seed data must NOT use deterministic role GUIDs
SEED_ALL_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
SEED_CONST_FILES=$(find src/ -path "*/Seeding/*" -name "SeedConstants.cs" 2>/dev/null)
if [ -n "$SEED_ALL_FILES" ]; then
  BAD_ROLE_GUID=$(grep -Pn 'DeterministicGuid\("role:' $SEED_ALL_FILES $SEED_CONST_FILES 2>/dev/null || true)
  if [ -n "$BAD_ROLE_GUID" ]; then
    echo "WARNING: Deterministic GUID for role detected (e.g., DeterministicGuid(\"role:admin\"))"
    echo "System roles are pre-seeded by SmartStack core with their own IDs"
    echo "Fix: In SeedRolePermissionsAsync(), look up roles by Code:"
    echo "  var roles = await context.Roles.Where(r => r.IsSystem || r.ApplicationId != null).ToListAsync(ct);"
    echo "  var role = roles.FirstOrDefault(r => r.Code == mapping.RoleCode);"
    echo "$BAD_ROLE_GUID"
  fi
fi

ROLE_PERM_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*RolesSeedData.cs" 2>/dev/null)
if [ -n "$ROLE_PERM_FILES" ]; then
  BAD_ROLE_REF=$(grep -Pn 'GenerateRoleGuid|GetAdminRoleId|GetManagerRoleId|GetViewerRoleId|GetContributorRoleId' $ROLE_PERM_FILES 2>/dev/null || true)
  if [ -n "$BAD_ROLE_REF" ]; then
    echo "WARNING: RolesSeedData uses hardcoded role GUID helpers instead of Code-based lookup"
    echo "Fix: Use RoleCode string (e.g., 'admin') and resolve in SeedRolePermissionsAsync()"
    echo "$BAD_ROLE_REF"
  fi
fi

# POST-CHECK C16: Cross-tenant entities must use Guid? TenantId
for entity in $(find src/ -path "*/Domain/*" -name "*.cs" ! -name "I*.cs" 2>/dev/null); do
  if grep -q "IOptionalTenantEntity\|IScopedTenantEntity" "$entity"; then
    if grep -q "public Guid TenantId" "$entity" && ! grep -q "public Guid? TenantId" "$entity"; then
      echo "CRITICAL: Entity with IOptionalTenantEntity/IScopedTenantEntity must use Guid? TenantId (nullable)"
      FAIL=true
    fi
  fi
done

# POST-CHECK C17: Scoped entities must have EntityScope property
for entity in $(find src/ -path "*/Domain/*" -name "*.cs" ! -name "I*.cs" 2>/dev/null); do
  if grep -q "IScopedTenantEntity" "$entity"; then
    if ! grep -q "EntityScope\|Scope" "$entity"; then
      echo "CRITICAL: Entity with IScopedTenantEntity must have EntityScope Scope property"
      FAIL=true
    fi
  fi
done

# POST-CHECK C18: Permissions.cs static constants must exist (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  PERM_REFS=$(grep -ohP 'Permissions\.\w+\.\w+' $CTRL_FILES 2>/dev/null | sed 's/Permissions\.\([^.]*\)\..*/\1/' | sort -u || true)
  for MODULE in $PERM_REFS; do
    PERM_FILE=$(find src/ -name "Permissions.cs" -exec grep -l "static class $MODULE" {} \; 2>/dev/null || true)
    if [ -z "$PERM_FILE" ]; then
      echo "BLOCKING: Controller references Permissions.${MODULE}.* but no Permissions.cs defines static class ${MODULE}"
      echo "Fix: Create Application/Authorization/Permissions.cs with: public static class ${MODULE} { public const string Read = \"...\"; ... }"
      FAIL=true
    fi
  done
fi

# POST-CHECK C19: ApplicationRolesSeedData.cs must exist (BLOCKING)
ROLE_SEED=$(find src/ -path "*/Seeding/Data/*" -name "*RolesSeedData.cs" 2>/dev/null | head -1)
if [ -n "$ROLE_SEED" ]; then
  APP_ROLE_SEED=$(find src/ -path "*/Seeding/Data/ApplicationRolesSeedData.cs" 2>/dev/null | head -1)
  if [ -z "$APP_ROLE_SEED" ]; then
    echo "BLOCKING: RolesSeedData exists but ApplicationRolesSeedData.cs NOT FOUND"
    echo "ApplicationRolesSeedData defines the 4 application-scoped roles (admin, manager, contributor, viewer)"
    echo "Without it, SeedRolesAsync() has no role entries to create → RBAC broken"
    echo "Fix: Create src/Infrastructure/Persistence/Seeding/Data/ApplicationRolesSeedData.cs"
    FAIL=true
  fi
fi

# POST-CHECK C20: Section route completeness (NavigationSection → frontend route + permissions)
SECTION_SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*NavigationSectionSeedData.cs" 2>/dev/null)
APP_TSX=$(find src/ -name "App.tsx" -not -path "*/node_modules/*" 2>/dev/null | head -1)
if [ -n "$SECTION_SEED_FILES" ] && [ -n "$APP_TSX" ]; then
  SECTION_ROUTES=$(grep -Poh '"/[a-z][a-z0-9/-]+"' $SECTION_SEED_FILES 2>/dev/null | tr -d '"' | sort -u || true)
  for SECTION_ROUTE in $SECTION_ROUTES; do
    SECTION_SEG=$(echo "$SECTION_ROUTE" | rev | cut -d'/' -f1 | rev)
    if ! grep -q "'$SECTION_SEG'" "$APP_TSX" && ! grep -q "\"$SECTION_SEG\"" "$APP_TSX"; then
      echo "WARNING: NavigationSection seed data route has no matching frontend route: $SECTION_ROUTE"
      echo "Expected path segment '$SECTION_SEG' in App.tsx application route block"
      echo "Fix: Add section child routes to the module's children array in App.tsx"
    fi
  done
fi

CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  for f in $CTRL_FILES; do
    SECTION_NAVROUTE=$(grep -oP 'NavRoute\("[a-z-]+\.[a-z-]+' "$f" 2>/dev/null)
    if [ -n "$SECTION_NAVROUTE" ] && ! grep -q "\[RequirePermission" "$f"; then
      echo "CRITICAL: Controller has [NavRoute] but no [RequirePermission]: $f"
      echo "Fix: Add [RequirePermission(Permissions.{Section}.{Action})] on each endpoint"
      FAIL=true
    fi
  done
fi

PERM_FILE=$(find src/ -name "Permissions.cs" -path "*/Authorization/*" 2>/dev/null | head -1)
if [ -n "$SECTION_SEED_FILES" ] && [ -n "$PERM_FILE" ]; then
  SECTION_CODES=$(grep -oP 'Code\s*=\s*"([a-z]+)"' $SECTION_SEED_FILES 2>/dev/null | grep -oP '"[^"]+"' | tr -d '"' | sort -u || true)
  for CODE in $SECTION_CODES; do
    PASCAL=$(echo "$CODE" | sed 's/^./\U&/')
    if ! grep -q "static class $PASCAL" "$PERM_FILE" 2>/dev/null; then
      echo "WARNING: Section '$CODE' in seed data has no matching Permissions.$PASCAL static class"
      echo "Fix: Add section-level permissions via MCP generate_permissions with 3-segment navRoute (app.module.section)"
    fi
  done
fi

# POST-CHECK C21: FORBIDDEN route patterns — /list and /detail/:id (WARNING)
SEED_NAV_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*NavigationSeedData.cs" -o -name "*NavigationSectionSeedData.cs" 2>/dev/null)
if [ -n "$SEED_NAV_FILES" ]; then
  BAD_ROUTES=$(grep -Pn 'Route\s*=\s*.*"[^"]*/(list|detail)["/]' $SEED_NAV_FILES 2>/dev/null | grep -v '//.*Route' || true)
  if [ -n "$BAD_ROUTES" ]; then
    echo "WARNING: FORBIDDEN route pattern in seed data"
    echo "  - 'list' section route = module route (NO /list suffix)"
    echo "  - 'detail' section route = module route + /:id (NOT /detail/:id)"
    echo "$BAD_ROUTES"
  fi
fi

APP_TSX=$(find src/ -name "App.tsx" -not -path "*/node_modules/*" 2>/dev/null | head -1)
if [ -n "$APP_TSX" ]; then
  BAD_FE=$(grep -Pn "path:\s*['\"](?:list|detail)" "$APP_TSX" 2>/dev/null || true)
  if [ -n "$BAD_FE" ]; then
    echo "WARNING: FORBIDDEN frontend route path"
    echo "  - list = index: true (no 'list' path segment)"
    echo "  - detail = ':id' (no 'detail' path segment)"
    echo "$BAD_FE"
  fi
fi

# POST-CHECK C22: Permission path segment count (WARNING)
PERM_FILES=$(find src/ -path "*/Seeding/Data/*" -name "PermissionsSeedData.cs" 2>/dev/null)
if [ -n "$PERM_FILES" ]; then
  while IFS= read -r line; do
    PATH_VAL=$(echo "$line" | grep -oP '"[^"]*\.[^"]*"' | tr -d '"' || true)
    if [ -n "$PATH_VAL" ]; then
      DOTS=$(echo "$PATH_VAL" | tr -cd '.' | wc -c)
      if echo "$PATH_VAL" | grep -qP '\.\*$'; then
        continue
      elif [ "$DOTS" -lt 2 ] || [ "$DOTS" -gt 4 ]; then
        echo "WARNING: Permission path has unexpected segment count ($((DOTS+1)) segments): $PATH_VAL"
      fi
    fi
  done < <(grep -n 'Path\s*=' $PERM_FILES 2>/dev/null)
fi

# POST-CHECK C23: IClientSeedDataProvider must have 4 methods + DI registration (BLOCKING)
PROVIDER=$(find src/ -path "*/Seeding/*SeedDataProvider.cs" 2>/dev/null | head -1)
if [ -n "$PROVIDER" ]; then
  METHODS_FOUND=0
  for METHOD in SeedNavigationAsync SeedRolesAsync SeedPermissionsAsync SeedRolePermissionsAsync; do
    if grep -q "$METHOD" "$PROVIDER"; then
      METHODS_FOUND=$((METHODS_FOUND + 1))
    else
      echo "BLOCKING: IClientSeedDataProvider missing method: $METHOD in $PROVIDER"
      FAIL=true
    fi
  done
  if [ "$METHODS_FOUND" -lt 4 ]; then
    echo "Fix: IClientSeedDataProvider must implement all 4 methods: SeedNavigationAsync, SeedRolesAsync, SeedPermissionsAsync, SeedRolePermissionsAsync"
  fi

  DI_FILE=$(find src/ -name "DependencyInjection.cs" -path "*/Infrastructure/*" 2>/dev/null | head -1)
  if [ -n "$DI_FILE" ]; then
    if ! grep -q "IClientSeedDataProvider" "$DI_FILE"; then
      echo "BLOCKING: IClientSeedDataProvider not registered in DependencyInjection.cs"
      echo "Fix: Add services.AddScoped<IClientSeedDataProvider, {App}SeedDataProvider>()"
      FAIL=true
    fi
  fi
fi

# POST-CHECK C32: Translation seed data must have idempotency guard (CRITICAL)
PROVIDER=$(find src/ -path "*/Seeding/*SeedDataProvider.cs" 2>/dev/null | head -1)
if [ -n "$PROVIDER" ]; then
  TRANSLATION_ADDS=$(grep -c "NavigationTranslations.Add" "$PROVIDER" 2>/dev/null || true)
  TRANSLATION_GUARDS=$(grep -c "NavigationTranslations.AnyAsync" "$PROVIDER" 2>/dev/null || true)

  if [ "$TRANSLATION_ADDS" -gt 0 ] && [ "$TRANSLATION_GUARDS" -eq 0 ]; then
    echo "CRITICAL: Translation seed data inserts without idempotency guard in $PROVIDER"
    echo "Fix: Before each NavigationTranslations.Add block, check existence:"
    echo "  if (!await context.NavigationTranslations.AnyAsync("
    echo "      t => t.EntityId == mod1Entity.Id  // actual DB ID, NOT seed-time GUID"
    echo "           && t.EntityType == NavigationEntityType.Module, ct))"
    echo "  { foreach (var t in ...) { context.NavigationTranslations.Add(...); } }"
    echo "The unique index IX_nav_Translations_EntityType_EntityId_LanguageCode will crash on duplicates."
    FAIL=true
  fi
fi

# POST-CHECK C33: Resource seed data must use actual section IDs from DB (CRITICAL)
PROVIDER=$(find src/ -path "*/Seeding/*SeedDataProvider.cs" 2>/dev/null | head -1)
if [ -n "$PROVIDER" ]; then
  if grep -Pn 'NavigationResource\.Create\(' "$PROVIDER" | grep -q 'resEntry\.SectionId\|secEntry\.Id'; then
    echo "CRITICAL: Resource seed data uses seed-time GUID as SectionId in $PROVIDER"
    echo "NavigationSection.Create() generates its own ID — seed-time GUIDs do NOT exist in nav_Sections."
    echo "Fix: Query actual section from DB before creating resources:"
    echo "  var actualSection = await context.NavigationSections"
    echo "      .FirstAsync(s => s.Code == secEntry.Code && s.ModuleId == modEntity.Id, ct);"
    echo "  NavigationResource.Create(actualSection.Id, ...)  // NOT secEntry.Id or resEntry.SectionId"
    FAIL=true
  fi
fi

# POST-CHECK C34: NavRoute segments must use kebab-case for multi-word codes (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  for f in $CTRL_FILES; do
    NAVROUTE_VAL=$(grep -oP 'NavRoute\("([^"]+)"\)' "$f" 2>/dev/null | grep -oP '"[^"]+"' | tr -d '"' || true)
    if [ -n "$NAVROUTE_VAL" ]; then
      for SEG in $(echo "$NAVROUTE_VAL" | tr '.' '\n'); do
        if echo "$SEG" | grep -qP '^[a-z]{10,}$'; then
          echo "BLOCKING: NavRoute segment '$SEG' in $f appears to be concatenated multi-word without hyphens"
          echo "  Full NavRoute: $NAVROUTE_VAL"
          echo "  Fix: Use kebab-case: e.g., 'humanresources' → 'human-resources'"
          echo "  SmartStack convention (from SmartStack.app): 'support-client.my-tickets'"
          FAIL=true
        fi
      done
    fi
  done
fi

SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*NavigationSeedData.cs" -o -name "NavigationApplicationSeedData.cs" 2>/dev/null)
if [ -n "$SEED_FILES" ]; then
  CODES=$(grep -oP 'Code\s*=\s*"([^"]+)"' $SEED_FILES 2>/dev/null | grep -oP '"[^"]+"' | tr -d '"' | sort -u || true)
  for CODE in $CODES; do
    if echo "$CODE" | grep -qP '^[a-z]{10,}$'; then
      echo "BLOCKING: Navigation seed data Code '$CODE' appears to be concatenated multi-word without hyphens"
      echo "  Fix: Use kebab-case: e.g., 'humanresources' → 'human-resources'"
      FAIL=true
    fi
  done
fi

# POST-CHECK C35: Permission codes must use kebab-case matching NavRoute codes (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  for f in $CTRL_FILES; do
    PERM_VALS=$(grep -oP 'RequirePermission\("([^"]+)"\)' "$f" 2>/dev/null | grep -oP '"[^"]+"' | tr -d '"' || true)
    for PERM in $PERM_VALS; do
      SEGMENTS=$(echo "$PERM" | tr '.' '\n' | head -n -1)
      for SEG in $SEGMENTS; do
        if echo "$SEG" | grep -qP '^[a-z]{10,}$'; then
          echo "BLOCKING: Permission code segment '$SEG' in $f appears concatenated without hyphens"
          echo "  Full permission: $PERM"
          echo "  Fix: Use kebab-case: e.g., 'humanresources' → 'human-resources'"
          echo "  SmartStack convention: 'support-client.my-tickets.read'"
          FAIL=true
        fi
      done
    done
  done
fi

PERM_FILES=$(find src/ -path "*/Authorization/Permissions.cs" 2>/dev/null)
if [ -n "$PERM_FILES" ]; then
  for f in $PERM_FILES; do
    CONST_VALS=$(grep -oP '=\s*"([^"]+)"' "$f" 2>/dev/null | grep -oP '"[^"]+"' | tr -d '"' || true)
    for PERM in $CONST_VALS; do
      SEGMENTS=$(echo "$PERM" | tr '.' '\n' | head -n -1)
      for SEG in $SEGMENTS; do
        if echo "$SEG" | grep -qP '^[a-z]{10,}$'; then
          echo "BLOCKING: Permissions.cs constant segment '$SEG' in $f appears concatenated without hyphens"
          echo "  Full permission: $PERM"
          echo "  Fix: Use kebab-case: e.g., 'humanresources' → 'human-resources'"
          FAIL=true
        fi
      done
    done
  done
fi

SEED_PERM_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*PermissionsSeedData.cs" 2>/dev/null)
if [ -n "$SEED_PERM_FILES" ]; then
  PATHS=$(grep -oP '"[a-z][a-z0-9.-]+\.(read|create|update|delete|\*)"' $SEED_PERM_FILES 2>/dev/null | tr -d '"' || true)
  for PERM in $PATHS; do
    SEGMENTS=$(echo "$PERM" | tr '.' '\n' | head -n -1)
    for SEG in $SEGMENTS; do
      if echo "$SEG" | grep -qP '^[a-z]{10,}$'; then
        echo "BLOCKING: PermissionsSeedData path segment '$SEG' appears concatenated without hyphens"
        echo "  Full permission path: $PERM"
        echo "  Fix: Use kebab-case matching NavRoute: 'humanresources' → 'human-resources'"
        FAIL=true
      fi
    done
  done
fi

# POST-CHECK C44: RolesSeedData must map standard role-permission matrix (CRITICAL)
ROLE_SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*RolesSeedData.cs" ! -name "ApplicationRolesSeedData.cs" 2>/dev/null)
if [ -n "$ROLE_SEED_FILES" ]; then
  FAIL_C44=false
  for f in $ROLE_SEED_FILES; do
    BASENAME=$(basename "$f")
    if [ "$BASENAME" = "ApplicationRolesSeedData.cs" ]; then continue; fi

    HAS_ADMIN_WILDCARD=$(grep -Pc '(admin|Admin).*\*' "$f" 2>/dev/null || true)
    if [ "$HAS_ADMIN_WILDCARD" -eq 0 ]; then
      HAS_ADMIN_ACCESS=$(grep -Pc '(admin|Admin).*(Access|Wildcard|IsWildcard)' "$f" 2>/dev/null || true)
      if [ "$HAS_ADMIN_ACCESS" -eq 0 ]; then
        echo "CRITICAL: Admin role missing wildcard (*) permission in $f"
        echo "Fix: Admin must map to wildcard permission (navRoute.*) or use IsWildcard=true"
        FAIL_C44=true
      fi
    fi

    VIEWER_WRITE=$(grep -Pc '(viewer|Viewer).*(\.delete|\.create|\.update|Delete|Create|Update)' "$f" 2>/dev/null || true)
    if [ "$VIEWER_WRITE" -gt 0 ]; then
      echo "CRITICAL: Viewer role has write permissions (create/update/delete) in $f"
      echo "Fix: Viewer must only have read permission. Remove create/update/delete mappings."
      FAIL_C44=true
    fi

    MANAGER_DELETE=$(grep -Pc '(manager|Manager).*(\.delete|Delete)' "$f" 2>/dev/null || true)
    if [ "$MANAGER_DELETE" -gt 0 ]; then
      echo "WARNING: Manager role has delete permission in $f"
      echo "SmartStack standard: Manager = CRU (no delete). Verify this is intentional."
    fi
  done
  if [ "$FAIL_C44" = true ]; then
    FAIL=true
  fi
fi

# POST-CHECK C45: PermissionAction enum must use valid typed values only (BLOCKING)
SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
if [ -n "$SEED_FILES" ]; then
  FAIL_C45=false
  for f in $SEED_FILES; do
    ENUM_PARSE=$(grep -Pn 'Enum\.Parse<PermissionAction>' "$f" 2>/dev/null || true)
    if [ -n "$ENUM_PARSE" ]; then
      echo "BLOCKING: Enum.Parse<PermissionAction> detected — runtime crash risk: $f"
      echo "$ENUM_PARSE"
      echo "Fix: Use typed enum directly: PermissionAction.Read (NOT Enum.Parse<PermissionAction>(\"Read\"))"
      FAIL_C45=true
    fi

    INVALID_CAST=$(grep -Pn '\(PermissionAction\)\s*([1-9]\d{1,}|[2-9]\d)' "$f" 2>/dev/null || true)
    if [ -n "$INVALID_CAST" ]; then
      echo "BLOCKING: Invalid PermissionAction cast detected (value > 10): $f"
      echo "$INVALID_CAST"
      echo "Valid values: Access(0), Read(1), Create(2), Update(3), Delete(4), Export(5), Import(6), Approve(7), Reject(8), Assign(9), Execute(10)"
      FAIL_C45=true
    fi
  done
  if [ "$FAIL_C45" = true ]; then
    FAIL=true
  fi
fi

# POST-CHECK C46: Navigation translation completeness — 4 languages per level (WARNING)
NAV_SEED_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*NavigationSeedData.cs" ! -name "*Application*" 2>/dev/null)
if [ -n "$NAV_SEED_FILES" ]; then
  FAIL_C46=false
  for f in $NAV_SEED_FILES; do
    HAS_FR=$(grep -c '"fr"' "$f" 2>/dev/null || true)
    HAS_EN=$(grep -c '"en"' "$f" 2>/dev/null || true)
    HAS_IT=$(grep -c '"it"' "$f" 2>/dev/null || true)
    HAS_DE=$(grep -c '"de"' "$f" 2>/dev/null || true)

    if [ "$HAS_FR" -eq 0 ] || [ "$HAS_EN" -eq 0 ] || [ "$HAS_IT" -eq 0 ] || [ "$HAS_DE" -eq 0 ]; then
      echo "WARNING: Missing language(s) in navigation translations: $f"
      echo "  fr=$HAS_FR, en=$HAS_EN, it=$HAS_IT, de=$HAS_DE (all must be > 0)"
      echo "Fix: Add NavigationTranslationSeedEntry for all 4 languages (fr, en, it, de)"
      FAIL_C46=true
    fi

    HAS_SECTION_ENTRIES=$(grep -c 'GetSectionEntries' "$f" 2>/dev/null || true)
    HAS_SECTION_TRANSLATIONS=$(grep -c 'GetSectionTranslationEntries' "$f" 2>/dev/null || true)
    if [ "$HAS_SECTION_ENTRIES" -gt 0 ] && [ "$HAS_SECTION_TRANSLATIONS" -eq 0 ]; then
      echo "WARNING: Sections defined but GetSectionTranslationEntries() missing: $f"
      echo "Fix: Add GetSectionTranslationEntries() with 4 languages per section (ref core-seed-data.md §2b)"
      FAIL_C46=true
    fi

    HAS_RESOURCE_ENTRIES=$(grep -c 'GetResourceEntries' "$f" 2>/dev/null || true)
    HAS_RESOURCE_TRANSLATIONS=$(grep -Pc 'ResourceTranslation|GetResourceTranslation|NavigationEntityType\.Resource.*LanguageCode' "$f" 2>/dev/null || true)
    if [ "$HAS_RESOURCE_ENTRIES" -gt 0 ] && [ "$HAS_RESOURCE_TRANSLATIONS" -eq 0 ]; then
      echo "WARNING: Resources defined but resource translations missing: $f"
      echo "Fix: Add resource translation entries with 4 languages per resource (ref core-seed-data.md §2b)"
      FAIL_C46=true
    fi
  done
fi

# POST-CHECK C47: Person Extension entities must not duplicate User fields (WARNING)
ENTITY_FILES=$(find src/ -path "*/Domain/Entities/*" -name "*.cs" 2>/dev/null)
if [ -n "$ENTITY_FILES" ]; then
  FAIL_C47=false
  for f in $ENTITY_FILES; do
    HAS_USERID=$(grep -P 'public\s+Guid\s+UserId\s*\{' "$f" 2>/dev/null || true)
    if [ -z "$HAS_USERID" ]; then continue; fi

    IS_MANDATORY=$(grep -P 'public\s+Guid\s+UserId\s*\{' "$f" 2>/dev/null | grep -v 'Guid?' || true)
    if [ -z "$IS_MANDATORY" ]; then continue; fi

    if ! grep -q "ITenantEntity" "$f"; then continue; fi

    PERSON_FIELDS=$(grep -Pn 'public\s+string\S*\s+(FirstName|LastName|Email|PhoneNumber)\s*\{' "$f" 2>/dev/null || true)
    if [ -n "$PERSON_FIELDS" ]; then
      echo "WARNING: Mandatory person extension entity duplicates User fields: $f"
      echo "  Entity has non-nullable UserId (mandatory variant) — person fields come from User"
      echo "$PERSON_FIELDS"
      echo "  Fix: Remove FirstName/LastName/Email/PhoneNumber — use Display* from User join in ResponseDto"
      echo "  See references/person-extension-pattern.md section 2"
      FAIL_C47=true
    fi
  done
fi

# POST-CHECK C48: Person Extension service must Include(User) (CRITICAL)
ENTITY_FILES=$(find src/ -path "*/Domain/Entities/*" -name "*.cs" 2>/dev/null)
if [ -n "$ENTITY_FILES" ]; then
  FAIL_C48=false
  for f in $ENTITY_FILES; do
    HAS_USERID=$(grep -P 'public\s+Guid\??\s+UserId\s*\{' "$f" 2>/dev/null || true)
    if [ -z "$HAS_USERID" ]; then continue; fi
    if ! grep -q "ITenantEntity" "$f"; then continue; fi

    HAS_USER_NAV=$(grep -P 'public\s+User\?\s+User\s*\{' "$f" 2>/dev/null || true)
    if [ -z "$HAS_USER_NAV" ]; then continue; fi

    ENTITY_NAME=$(basename "$f" .cs)
    SERVICE_FILE=$(find src/ -path "*/Services/*" -name "${ENTITY_NAME}Service.cs" ! -name "I${ENTITY_NAME}Service.cs" 2>/dev/null | head -1)
    if [ -z "$SERVICE_FILE" ]; then continue; fi

    HAS_INCLUDE=$(grep -P 'Include.*User' "$SERVICE_FILE" 2>/dev/null || true)
    if [ -z "$HAS_INCLUDE" ]; then
      echo "CRITICAL: Service for Person Extension entity must Include(x => x.User): $SERVICE_FILE"
      echo "  Entity: $f has UserId FK + User navigation property"
      echo "  Fix: Add .Include(x => x.User) to all queries in $SERVICE_FILE"
      echo "  Without Include, Display* fields will always be null"
      echo "  See references/person-extension-pattern.md section 5"
      FAIL_C48=true
    fi
  done
  if [ "$FAIL_C48" = true ]; then
    FAIL=true
  fi
fi

# POST-CHECK C53: Enum serialization — JsonStringEnumConverter required (BLOCKING)
PROGRAM_CS=$(find src/ -name "Program.cs" -path "*/Api/*" 2>/dev/null | head -1)
HAS_GLOBAL_CONVERTER=false
if [ -n "$PROGRAM_CS" ] && grep -q "JsonStringEnumConverter" "$PROGRAM_CS" 2>/dev/null; then
  HAS_GLOBAL_CONVERTER=true
fi

if [ "$HAS_GLOBAL_CONVERTER" = false ]; then
  ENUM_FILES=$(find src/ -path "*/Domain/Enums/*" -name "*.cs" 2>/dev/null)
  if [ -n "$ENUM_FILES" ]; then
    for f in $ENUM_FILES; do
      if grep -q "public enum" "$f" && ! grep -q "JsonStringEnumConverter" "$f"; then
        echo "BLOCKING: Enum missing [JsonConverter(typeof(JsonStringEnumConverter))]: $f"
        echo "  Frontend sends enum values as strings but C# deserializes as int by default"
        echo "  Fix: Add [JsonConverter(typeof(JsonStringEnumConverter))] on the enum"
        echo "  Or: Add JsonStringEnumConverter globally in Program.cs"
        FAIL=true
      fi
    done
  fi
fi

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