#!/bin/bash
set -euo pipefail

# POST-CHECK: Infrastructure — Migration & Build
# C13, C38-C43, C50-C51, C56, C60-C61: Database migrations, DI registration, routing uniqueness, MCP compliance

FAIL=false

# POST-CHECK C13: i18n files must contain required structural keys
I18N_DIR="src/i18n/locales/fr"
if [ -d "$I18N_DIR" ]; then
  REQUIRED_KEYS="actions columns empty errors form labels messages validation"
  for JSON_FILE in "$I18N_DIR"/*.json; do
    [ ! -f "$JSON_FILE" ] && continue
    BASENAME=$(basename "$JSON_FILE")
    case "$BASENAME" in common.json|navigation.json) continue;; esac
    for KEY in $REQUIRED_KEYS; do
      if ! jq -e "has(\"$KEY\")" "$JSON_FILE" > /dev/null 2>&1; then
        echo "WARNING: i18n file missing required key '$KEY': $JSON_FILE"
        echo "Module i18n files MUST contain: $REQUIRED_KEYS"
      fi
    done
  done
fi

# POST-CHECK C38: Migration ModelSnapshot must contain ALL entities registered in DbContext (BLOCKING)
SNAPSHOT=$(find src/ -name "*ModelSnapshot.cs" -path "*/Migrations/*" 2>/dev/null | head -1)
DBCONTEXT=$(find src/ -name "*DbContext.cs" -path "*/Persistence/*" ! -name "*DesignTime*" 2>/dev/null | head -1)
if [ -n "$SNAPSHOT" ] && [ -n "$DBCONTEXT" ]; then
  DBSET_ENTITIES=$(grep -o 'DbSet<[A-Za-z0-9_]*>' "$DBCONTEXT" 2>/dev/null | sed 's/DbSet<//;s/>//' | sort -u || true)
  FAIL_C38=false
  for ENTITY in $DBSET_ENTITIES; do
    if echo "$ENTITY" | grep -qE '^(Navigation|Tenant|User|Role|Permission|AuditLog|ApplicationTracking)'; then
      continue
    fi
    if ! grep -q "Entity<$ENTITY>" "$SNAPSHOT" 2>/dev/null; then
      echo "BLOCKING: Entity '$ENTITY' is registered as DbSet in $DBCONTEXT but MISSING from ModelSnapshot"
      echo "  This means no migration was created for this entity — it will not exist in the database."
      echo "  Fix: Run 'dotnet ef migrations add' to include all new entities"
      FAIL_C38=true
    fi
  done
  if [ "$FAIL_C38" = true ]; then
    echo ""
    echo "  Root cause: Migration was likely created once for the first batch of entities,"
    echo "  but additional entities were added later without regenerating the migration."
    echo "  Fix: Create a new migration that covers ALL missing entities."
    FAIL=true
  fi
fi

# POST-CHECK C39: I18n namespace files must be registered in i18n config (CRITICAL)
I18N_CONFIG=$(find src/ web/ -path "*/i18n/config.ts" -o -path "*/i18n/index.ts" -o -path "*/i18n/i18n.ts" 2>/dev/null | grep -v node_modules | head -1)
if [ -n "$I18N_CONFIG" ]; then
  FR_FILES=$(find src/ web/ -path "*/i18n/locales/fr/*.json" 2>/dev/null | grep -v node_modules | grep -v common.json | grep -v navigation.json || true)
  if [ -n "$FR_FILES" ]; then
    FAIL_C39=false
    for JSON_FILE in $FR_FILES; do
      NS=$(basename "$JSON_FILE" .json)
      if ! grep -q "$NS" "$I18N_CONFIG" 2>/dev/null; then
        echo "CRITICAL: i18n namespace '$NS' (from $JSON_FILE) is not registered in $I18N_CONFIG"
        echo "  Pages using useTranslation(['$NS']) will get empty translations at runtime"
        echo "  Fix: Add '$NS' to the resources/ns configuration in $I18N_CONFIG"
        FAIL_C39=true
      fi
    done
    if [ "$FAIL_C39" = true ]; then
      FAIL=true
    fi
  fi
fi

# POST-CHECK C40: FluentValidation validators must be registered via DI (BLOCKING)
VALIDATOR_FILES=$(find src/ -name "*Validator.cs" -path "*/Validators/*" 2>/dev/null | grep -v test | grep -v Test)
if [ -n "$VALIDATOR_FILES" ]; then
  DI_FILE=$(find src/ -name "DependencyInjection.cs" -o -name "ServiceCollectionExtensions.cs" 2>/dev/null | grep -v test | head -1)
  if [ -z "$DI_FILE" ]; then
    echo "BLOCKING: Validators exist but no DependencyInjection.cs found for DI registration"
    FAIL=true
  else
    HAS_ASSEMBLY_REG=$(grep -c "AddValidatorsFromAssembly\|AddValidatorsFromAssemblyContaining" "$DI_FILE" 2>/dev/null || true)
    if [ "$HAS_ASSEMBLY_REG" -eq 0 ]; then
      VALIDATOR_COUNT=$(echo "$VALIDATOR_FILES" | wc -l)
      REGISTERED_COUNT=0
      for VF in $VALIDATOR_FILES; do
        VN=$(basename "$VF" .cs)
        if grep -q "$VN" "$DI_FILE" 2>/dev/null; then
          REGISTERED_COUNT=$((REGISTERED_COUNT + 1))
        fi
      done
      if [ "$REGISTERED_COUNT" -eq 0 ]; then
        echo "BLOCKING: $VALIDATOR_COUNT validators exist but NONE are registered in DI ($DI_FILE)"
        echo "  Fix: Add 'services.AddValidatorsFromAssemblyContaining<Create{Entity}DtoValidator>();' to $DI_FILE"
        echo "  Or use 'services.AddValidatorsFromAssembly(typeof(Create{Entity}DtoValidator).Assembly);'"
        FAIL=true
      fi
    fi
  fi
fi

# POST-CHECK C41: Date/date properties in DTOs must use DateOnly, not string (WARNING)
DTO_FILES=$(find src/ -name "*Dto.cs" -path "*/DTOs/*" 2>/dev/null)
if [ -n "$DTO_FILES" ]; then
  FAIL_C41=false
  for f in $DTO_FILES; do
    BAD_DATES=$(grep -nE 'string\??\s+[A-Za-z0-9_]*[Dd]ate[A-Za-z0-9_]*\s*[{;,]' "$f" 2>/dev/null | grep -vi "Updated\|Created\|format\|pattern\|string\|parse" || true)
    if [ -n "$BAD_DATES" ]; then
      echo "WARNING: DTO has string type for date field — must use DateOnly: $f"
      echo "$BAD_DATES"
      echo "  Fix: Change 'string Date' to 'DateOnly Date' (or 'DateOnly? Date' if nullable)"
      echo "  DateOnly is the correct .NET type for date-only values (no time component)"
    fi
  done
fi

# POST-CHECK C42: Every module with entities must have a migration covering them (BLOCKING)
ENTITY_FILES=$(find src/ -path "*/Domain/Entities/*" -name "*.cs" 2>/dev/null | grep -v test || true)
MIGRATION_DIR=$(find src/ -path "*/Migrations" -type d 2>/dev/null | head -1)
if [ -n "$ENTITY_FILES" ] && [ -n "$MIGRATION_DIR" ]; then
  MIGRATION_FILES=$(find "$MIGRATION_DIR" -name "*.cs" ! -name "*ModelSnapshot*" ! -name "*DesignTime*" 2>/dev/null)
  if [ -z "$MIGRATION_FILES" ]; then
    echo "BLOCKING: Entity files exist in Domain/Entities but NO migration files found in $MIGRATION_DIR"
    FAIL=true
  else
    FAIL_C42=false
    for EF in $ENTITY_FILES; do
      ENTITY_NAME=$(basename "$EF" .cs)
      if grep -qE '^\s*(public\s+)?(abstract|interface)\s' "$EF" 2>/dev/null; then continue; fi
      FOUND=$(grep -l "$ENTITY_NAME" $MIGRATION_FILES 2>/dev/null || true)
      if [ -z "$FOUND" ]; then
        echo "BLOCKING: Entity '$ENTITY_NAME' ($EF) not found in any migration file"
        echo "  This entity will NOT have a database table."
        echo "  Fix: Run 'dotnet ef migrations add' to create a migration covering this entity"
        FAIL_C42=true
      fi
    done
    if [ "$FAIL_C42" = true ]; then
      FAIL=true
    fi
  fi
fi

# POST-CHECK C43: Controllers must NOT have both [Route] and [NavRoute] attributes (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  FAIL_C43=false
  for f in $CTRL_FILES; do
    HAS_NAVROUTE=$(grep -c '\[NavRoute(' "$f" 2>/dev/null || true)
    HAS_ROUTE=$(grep -c '\[Route(' "$f" 2>/dev/null || true)
    if [ "$HAS_NAVROUTE" -gt 0 ] && [ "$HAS_ROUTE" -gt 0 ]; then
      NAVROUTE_VAL=$(grep -o 'NavRoute("[^"]*"' "$f" 2>/dev/null | head -1 || true)
      ROUTE_VAL=$(grep -o 'Route("[^"]*"' "$f" 2>/dev/null | head -1 || true)
      echo "BLOCKING: Controller has BOTH [Route] and [NavRoute] — remove [Route]: $f"
      echo "  Found: [$ROUTE_VAL] + [$NAVROUTE_VAL]"
      echo "  In SmartStack, [NavRoute] resolves routes dynamically from the database."
      echo "  Having [Route] alongside it causes route conflicts and 404s."
      echo "  Fix: Remove the [Route(...)] attribute, keep only [NavRoute(...)]"
      FAIL_C43=true
    fi
  done
  if [ "$FAIL_C43" = true ]; then
    FAIL=true
  fi
fi

# POST-CHECK C50: NavRoute Uniqueness — no duplicate NavRoute values (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  NAVROUTES=$(grep -n '\[NavRoute("' $CTRL_FILES 2>/dev/null | sed 's/.*\[NavRoute("\([^"]*\)".*/\1/' | sort || true)
  DUPLICATES=$(echo "$NAVROUTES" | uniq -d || true)
  if [ -n "$DUPLICATES" ]; then
    echo "BLOCKING: Duplicate NavRoute values detected:"
    for DUP in $DUPLICATES; do
      echo "  NavRoute: $DUP"
      grep -l "\[NavRoute(\"$DUP\")\]" $CTRL_FILES 2>/dev/null | while read -r f; do
        echo "    - $f"
      done
    done
    echo "  Fix: Each controller MUST have a unique NavRoute value"
    FAIL=true
  fi
fi

# POST-CHECK C51: NavRoute Segments vs Controller Hierarchy (WARNING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  for f in $CTRL_FILES; do
    NAVROUTE=$(grep -o 'NavRoute("[^"]*"' "$f" 2>/dev/null | sed 's/NavRoute("//;s/"//' | head -1 || true)
    if [ -z "$NAVROUTE" ]; then continue; fi

    DOTS=$(echo "$NAVROUTE" | tr -cd '.' | wc -c)

    REL_PATH=$(echo "$f" | sed 's|.*/Controllers/||')
    DIR_DEPTH=$(echo "$REL_PATH" | tr '/' '\n' | wc -l)

    if [ "$DIR_DEPTH" -ge 3 ] && [ "$DOTS" -le 1 ]; then
      echo "WARNING: Controller in section subfolder but NavRoute has only $((DOTS+1)) segments"
      echo "  File: $f"
      echo "  NavRoute: $NAVROUTE"
      echo "  Expected: 3+ segments (app.module.section) for controllers in section subfolders"
      echo "  Fix: Update NavRoute to include the module segment (e.g., 'app.module.section')"
    fi

    if [ "$DOTS" -eq 0 ]; then
      echo "BLOCKING: NavRoute '$NAVROUTE' has only 1 segment (minimum 2 required): $f"
      FAIL=true
    fi
  done
fi

# POST-CHECK C56: Hierarchy Artifact Completeness — current run only (BLOCKING)
# REQUIRES: {entities} and {sections} from current apex run context
# If not available, skip this check (cannot determine scope)

if [ -n "${ENTITIES:-}" ] && [ -n "${SECTIONS:-}" ]; then
  FAIL_C56=false

  for ENTITY in $ENTITIES; do
    CTRL=$(find src/ -path "*/Controllers/*" -name "${ENTITY}*Controller.cs" 2>/dev/null | head -1)
    if [ -z "$CTRL" ]; then
      echo "BLOCKING: Entity '$ENTITY' has no controller file"
      FAIL_C56=true
    fi
    if ! grep -q "\[NavRoute" "$CTRL" 2>/dev/null; then
      echo "BLOCKING: Controller for '$ENTITY' ($CTRL) missing [NavRoute] attribute"
      echo "SmartStack convention: [NavRoute] is the ONLY route attribute needed"
      FAIL_C56=true
    fi
    if grep -q "\[Route(" "$CTRL" 2>/dev/null && grep -q "\[NavRoute" "$CTRL" 2>/dev/null; then
      echo "BLOCKING: Controller $CTRL has BOTH [Route] and [NavRoute] (see C43)"
      FAIL_C56=true
    fi
  done

  PERM_SEED=$(find src/ -path "*/Seeding/Data/*" -name "*PermissionsSeedData.cs" 2>/dev/null)
  NAV_SEED=$(find src/ -path "*/Seeding/Data/*" -name "*NavigationSeedData.cs" ! -name "*Application*" 2>/dev/null)
  for SECTION in $SECTIONS; do
    if [ -n "$PERM_SEED" ] && ! grep -q "\"$SECTION\"" $PERM_SEED 2>/dev/null; then
      echo "BLOCKING: Section '$SECTION' missing from PermissionsSeedData"
      FAIL_C56=true
    fi
    if [ -n "$NAV_SEED" ] && ! grep -q "\"$SECTION\"" $NAV_SEED 2>/dev/null; then
      echo "BLOCKING: Section '$SECTION' missing from NavigationSeedData"
      FAIL_C56=true
    fi
  done

  if [ "$FAIL_C56" = true ]; then
    FAIL=true
  fi
fi

# POST-CHECK C60: Controllers must inject ISender _mediator, NOT direct business services (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  FAIL_C60=false
  for f in $CTRL_FILES; do
    # Detect direct business service injection (I{Entity}Service pattern)
    # Exclude infrastructure services: ICurrentTenantService, ICurrentUserService, IStringLocalizer
    DIRECT_SVC=$(grep -E 'private readonly I[A-Za-z0-9_]+Service ' "$f" 2>/dev/null | grep -v 'ICurrentTenantService\|ICurrentUserService\|IStringLocalizer' || true)
    if [ -n "$DIRECT_SVC" ] && ! grep -q 'ISender' "$f"; then
      echo "BLOCKING: Controller injects business service directly instead of ISender _mediator: $f"
      echo "  Found: $(echo "$DIRECT_SVC" | head -1 | xargs)"
      echo "  SmartStack convention: Controllers use MediatR (ISender) for CQRS dispatch"
      echo "  Fix: Regenerate via mcp__smartstack__scaffold_extension(type: 'controller')"
      FAIL_C60=true
    fi
  done
  if [ "$FAIL_C60" = true ]; then
    FAIL=true
  fi
fi

# POST-CHECK C61: Controllers with [NavRoute] must have [Authorize] attribute (BLOCKING)
CTRL_FILES=$(find src/ -path "*/Controllers/*" -name "*Controller.cs" 2>/dev/null)
if [ -n "$CTRL_FILES" ]; then
  FAIL_C61=false
  for f in $CTRL_FILES; do
    if grep -q '\[NavRoute' "$f" && ! grep -q '\[.*Authorize\]' "$f"; then
      echo "BLOCKING: Controller with [NavRoute] missing [Authorize]: $f"
      echo "  Fix: Add [Microsoft.AspNetCore.Authorization.Authorize] on class"
      FAIL_C61=true
    fi
  done
  if [ "$FAIL_C61" = true ]; then
    FAIL=true
  fi
fi

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