#!/usr/bin/env bash
set -euo pipefail

APP_DIR=${APP_DIR:-/var/www}
cd "$APP_DIR"

DB_HOST=${DB_HOST:-mysql}
DB_PORT=${DB_PORT:-3306}
DB_USERNAME=${DB_USERNAME:-winary_user}
DB_PASSWORD=${DB_PASSWORD:-winary_password}
DB_DATABASE=${DB_DATABASE:-laravel_winary}
APP_PORT=${APP_PORT:-8741}
NPM_INSTALL_ARGS=${NPM_INSTALL_ARGS:---no-fund --no-audit --no-progress}

prepare_cache_dirs() {
  mkdir -p bootstrap/cache \
           storage/logs \
           storage/framework/cache \
           storage/framework/views \
           storage/framework/sessions \
           storage/framework/testing
}

clear_cached_artifacts() {
  rm -f bootstrap/cache/*.php
}

ensure_php_dependencies() {
  if [ -f vendor/autoload.php ]; then
    return
  fi

  echo "Installing PHP dependencies..."
  composer install --no-dev --optimize-autoloader --no-interaction --no-progress
}

wait_for_database() {
  local attempt=0
  while true; do
    if php -r "
      \$host = getenv('DB_HOST') ?: 'mysql';
      \$port = getenv('DB_PORT') ?: '3306';
      \$db = getenv('DB_DATABASE') ?: 'laravel_winary';
      \$user = getenv('DB_USERNAME') ?: 'winary_user';
      \$pass = getenv('DB_PASSWORD') ?: 'winary_password';
      \$dsn = \"mysql:host=\$host;port=\$port;dbname=\$db\";
      try {
          new PDO(\$dsn, \$user, \$pass, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
      } catch (Exception \$e) {
          fwrite(STDERR, \$e->getMessage());
          exit(1);
      }
    "; then
      echo "Database is ready."
      break
    else
      attempt=$((attempt + 1))
      echo "Database not ready (attempt ${attempt}), retrying in 2s..."
      sleep 2
    fi
  done
}

install_node_dependencies() {
  if [ -d node_modules ]; then
    echo "Node dependencies already installed, skipping npm install."
  else
    echo "Installing Node dependencies..."
    npm ci $NPM_INSTALL_ARGS
  fi
}

build_assets() {
  echo "Building frontend assets..."
  npm run build
}

ensure_storage_symlink() {
  local link_path="public/storage"
  local desired_target="../storage/app/public"

  mkdir -p storage/app/public

  if [ -L "$link_path" ]; then
    local current_target
    current_target=$(readlink "$link_path")
    if [ "$current_target" = "$desired_target" ] || [ "$current_target" = "/var/www/storage/app/public" ]; then
      return
    fi

    echo "Updating storage symlink (was pointing to $current_target)..."
    rm "$link_path"
  elif [ -e "$link_path" ]; then
    echo "Removing existing public/storage to recreate symlink..."
    rm -rf "$link_path"
  fi

  if php artisan storage:link --relative >/dev/null 2>&1; then
    return
  fi

  ln -s "$desired_target" "$link_path"
}

ensure_docs_symlink() {
  local source_path="doc.html"
  local link_path="public/doc.html"

  if [ ! -f "$source_path" ]; then
    echo "doc.html not found at $source_path, skipping docs symlink."
    return
  fi

  mkdir -p public

  if [ -L "$link_path" ]; then
    local current_target
    current_target=$(readlink "$link_path")
    if [ "$current_target" = "../doc.html" ] || [ "$current_target" = "/var/www/doc.html" ]; then
      return
    fi

    echo "Updating doc.html symlink (was pointing to $current_target)..."
    rm "$link_path"
  elif [ -e "$link_path" ]; then
    echo "Removing existing public/doc.html to recreate symlink..."
    rm -rf "$link_path"
  fi

  ln -s ../doc.html "$link_path"
}

fix_permissions() {
  # Ensure runtime-writable dirs are accessible even on bind mounts
  chown -R www-data:www-data storage bootstrap/cache public/storage || true
  chmod -R ug+rwX storage bootstrap/cache public/storage || true
}

prepare_cache_dirs
clear_cached_artifacts

wait_for_database

ensure_php_dependencies
php artisan migrate:fresh --seed --force

install_node_dependencies
build_assets
ensure_storage_symlink
ensure_docs_symlink
fix_permissions

# Normalize command to always serve on configured APP_PORT when using artisan serve
if [ "$#" -eq 0 ]; then
  set -- php artisan serve --host=0.0.0.0 --port="${APP_PORT}"
elif [ "$1" = "php" ] && [ "${2:-}" = "artisan" ] && [ "${3:-}" = "serve" ]; then
  shift 3
  set -- php artisan serve --host=0.0.0.0 --port="${APP_PORT}" "$@"
fi

exec "$@"
