#!/bin/bash

# --- Color Definitions for Premium Look ---
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m' # No Color

echo -e "${BLUE}======================================================${NC}"
echo -e "${GREEN}    🐳 Biiproject Kit - Fully Containerized Setup 🐳   ${NC}"
echo -e "${BLUE}======================================================${NC}"

# 1. Pre-flight Checks (Docker & Daemon status)
echo -e "${BLUE}[1/8] Verifying Docker installation...${NC}"
if ! command -v docker &> /dev/null; then
    echo -e "  ${RED}Error: Docker is not installed on this system.${NC}"
    echo -e "  ${YELLOW}Please install Docker and Docker Compose before running this script.${NC}"
    exit 1
fi

if ! docker info &> /dev/null; then
    echo -e "  ${RED}Error: Docker daemon is not running.${NC}"
    echo -e "  ${YELLOW}Please start your Docker service and try again.${NC}"
    exit 1
fi
echo -e "  ${GREEN}✔ Docker is installed and running.${NC}"
echo ""

# 2. Prevent Port & Container conflicts
echo -e "${BLUE}[2/8] Checking for port conflicts...${NC}"

# Ensure .env is present to parse ports
if [ ! -f .env ] && [ -f .env.example ]; then
    cp .env.example .env
fi

# Resolve ports dynamically from .env or defaults
PORT_8000=$(grep "^APP_PORT=" .env 2>/dev/null | cut -d'=' -f2- | tr -d '"'\''')
PORT_8000=${PORT_8000:-8000}

PORT_5432=$(grep -E "^(FORWARD_DB_PORT|DB_PORT)=" .env 2>/dev/null | head -n1 | cut -d'=' -f2- | tr -d '"'\''')
PORT_5432=${PORT_5432:-5432}

PORT_6379=$(grep -E "^(FORWARD_REDIS_PORT|REDIS_PORT)=" .env 2>/dev/null | head -n1 | cut -d'=' -f2- | tr -d '"'\''')
PORT_6379=${PORT_6379:-6379}

# Stop local processes using these ports
if command -v lsof &>/dev/null && command -v fuser &>/dev/null; then
    for port in "$PORT_8000" "$PORT_5432" "$PORT_6379"; do
        if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null ; then
            echo -e "${YELLOW}Port $port is occupied by a local process. Stopping it...${NC}"
            fuser -k $port/tcp 2>/dev/null
            sleep 1
        fi
    done
fi

# Find the container names from our own docker-compose.yml to avoid stopping ourselves
MY_CONTAINERS=$(grep "container_name:" docker-compose.yml 2>/dev/null | awk '{print $2}' | tr -d '"'\''')

stop_conflict_on_port() {
    local port=$1
    local port_type=$2
    
    local conflicting_container=$(docker ps --filter "publish=$port" --format "{{.Names}}" 2>/dev/null)
    if [ ! -z "$conflicting_container" ]; then
        local is_ours=false
        for ours in $MY_CONTAINERS; do
            if [ "$conflicting_container" = "$ours" ]; then
                is_ours=true
                break
            fi
        done
        
        if [ "$is_ours" = "false" ]; then
            echo -e "${YELLOW}Port $port ($port_type) is occupied by container '$conflicting_container'. Stopping it...${NC}"
            docker stop "$conflicting_container" &>/dev/null
        fi
    fi
}

stop_conflict_on_port "$PORT_8000" "Web Server"
stop_conflict_on_port "$PORT_5432" "PostgreSQL Database"
stop_conflict_on_port "$PORT_6379" "Redis Cache"
echo -e "  ${GREEN}✔ Ports $PORT_8000, $PORT_5432, and $PORT_6379 are clear.${NC}"
echo ""

# 3. Environment File (.env) check
echo -e "${BLUE}[3/8] Checking configuration environment...${NC}"
if [ ! -f .env ]; then
    echo -e "  ${YELLOW}⚠ .env file not found. Creating from .env.example...${NC}"
    cp .env.example .env
    ENV_CREATED=true
else
    echo -e "  ${GREEN}✔ .env file already exists.${NC}"
    ENV_CREATED=false
fi
echo ""

# 4. Install Composer dependencies (Zero-Dependency Host)
echo -e "${BLUE}[4/8] Checking Composer dependencies...${NC}"
if [ ! -d vendor ]; then
    echo -e "  ${YELLOW}⚠ Vendor directory not found. Installing via lightweight PHP container...${NC}"
    docker run --rm \
        -u "$(id -u):$(id -g)" \
        -v "$(pwd):/var/www/html" \
        -w /var/www/html \
        laravelsail/php83-composer:latest \
        composer install --ignore-platform-reqs
    
    if [ $? -ne 0 ]; then
        echo -e "  ${RED}Error: Failed to install composer dependencies via Docker.${NC}"
        exit 1
    fi
    echo -e "  ${GREEN}✔ Composer dependencies installed successfully.${NC}"
else
    echo -e "  ${GREEN}✔ Composer dependencies are up to date.${NC}"
fi
echo ""

# 5. Start Docker Compose stack
echo -e "${BLUE}[5/8] Starting Docker Compose stack (Web, PGSQL, Redis)...${NC}"
docker compose up -d

if [ $? -ne 0 ]; then
    echo -e "  ${RED}Error: Failed to spin up Docker containers. Please check docker-compose.yml.${NC}"
    exit 1
fi
echo -e "  ${GREEN}✔ Docker Compose services started successfully.${NC}"
echo ""

# Resolve DB container dynamically
DB_CONTAINER=$(docker compose ps --format "{{.Name}}" pgsql 2>/dev/null)
if [ -z "$DB_CONTAINER" ]; then
    DB_CONTAINER=$(grep -A 10 -E "^  pgsql:" docker-compose.yml 2>/dev/null | grep "container_name:" | head -n1 | awk '{print $2}' | tr -d '"'\''')
fi
if [ -z "$DB_CONTAINER" ]; then
    DB_CONTAINER="bii-kit-pgsql"
fi

# Resolve Redis container dynamically
REDIS_CONTAINER=$(docker compose ps --format "{{.Name}}" redis 2>/dev/null)
if [ -z "$REDIS_CONTAINER" ]; then
    REDIS_CONTAINER=$(grep -A 10 -E "^  redis:" docker-compose.yml 2>/dev/null | grep "container_name:" | head -n1 | awk '{print $2}' | tr -d '"'\''')
fi
if [ -z "$REDIS_CONTAINER" ]; then
    REDIS_CONTAINER="bii-kit-redis"
fi

# 6. Wait for Databases to be ready (Self-Healing)
echo -e "${BLUE}[6/8] Waiting for services to be ready & configuring permissions...${NC}"

echo -ne "  ${YELLOW}Checking PostgreSQL database ($DB_CONTAINER)...${NC}"
RETRIES=0
MAX_RETRIES=40
while [ $RETRIES -lt $MAX_RETRIES ]; do
    STATUS=$(docker inspect --format='{{.State.Health.Status}}' "$DB_CONTAINER" 2>/dev/null)
    if [ "$STATUS" = "healthy" ]; then
        echo -e "\r  ${GREEN}✔ PostgreSQL is healthy and ready to accept connections!           ${NC}"
        break
    elif [ "$STATUS" = "unhealthy" ]; then
        echo -e "\r  ${RED}⚠ PostgreSQL health check reported unhealthy. Proceeding anyway...${NC}"
        break
    elif [ -z "$STATUS" ]; then
        # Check if container is at least running
        RUNNING=$(docker inspect --format='{{.State.Running}}' "$DB_CONTAINER" 2>/dev/null)
        if [ "$RUNNING" = "true" ]; then
            echo -e "\r  ${GREEN}✔ PostgreSQL container is running (no healthcheck status).         ${NC}"
            break
        fi
    fi
    echo -n "."
    sleep 1.5
    RETRIES=$((RETRIES + 1))
done

echo -ne "  ${YELLOW}Checking Redis cache ($REDIS_CONTAINER)...${NC}"
RETRIES=0
while [ $RETRIES -lt $MAX_RETRIES ]; do
    STATUS=$(docker inspect --format='{{.State.Health.Status}}' "$REDIS_CONTAINER" 2>/dev/null)
    if [ "$STATUS" = "healthy" ]; then
        echo -e "\r  ${GREEN}✔ Redis is healthy and ready to accept connections!                 ${NC}"
        break
    elif [ "$STATUS" = "unhealthy" ]; then
        echo -e "\r  ${RED}⚠ Redis health check reported unhealthy. Proceeding anyway...${NC}"
        break
    elif [ -z "$STATUS" ]; then
        # Check if container is at least running
        RUNNING=$(docker inspect --format='{{.State.Running}}' "$REDIS_CONTAINER" 2>/dev/null)
        if [ "$RUNNING" = "true" ]; then
            echo -e "\r  ${GREEN}✔ Redis container is running (no healthcheck status).               ${NC}"
            break
        fi
    fi
    echo -n "."
    sleep 1.5
    RETRIES=$((RETRIES + 1))
done

# Extra sleep to ensure Docker internal DNS has fully propagated the container names
sleep 2

# Correct any permission issues on build and storage folders before continuing
echo -ne "  ${YELLOW}Securing workspace file permissions...${NC}"
docker compose exec -u root laravel.test chown -R sail:sail /var/www/html/storage /var/www/html/bootstrap/cache 2>/dev/null
docker compose exec -u root laravel.test chmod -R 775 /var/www/html/storage /var/www/html/bootstrap/cache 2>/dev/null
if [ -d public/build ]; then
    docker compose exec -u root laravel.test chown -R sail:sail /var/www/html/public/build 2>/dev/null
    docker compose exec -u root laravel.test chmod -R 775 /var/www/html/public/build 2>/dev/null
fi
echo -e "\r  ${GREEN}✔ Workspace file permissions secured.                                ${NC}"
echo ""

# 7. Securing Application & Database Initialization
echo -e "${BLUE}[7/8] Securing application and preparing database...${NC}"

# Check for empty key
APP_KEY_VAL=$(grep "^APP_KEY=" .env | cut -d'=' -f2- | tr -d '"'\''')
if [ -z "$APP_KEY_VAL" ] || [ "$APP_KEY_VAL" = "base64:" ] || [ "$APP_KEY_VAL" = "SomeRandomString" ]; then
    echo -e "  ${YELLOW}Generating unique application encryption key...${NC}"
    docker compose exec -u sail laravel.test php artisan key:generate
fi

# Check if tables exist to decide fresh migrate & seed or regular migrate
TABLE_EXISTS=$(docker compose exec -u sail laravel.test php artisan tinker --execute="echo Schema::hasTable('users') ? 'yes' : 'no';" 2>/dev/null | tr -d '\r\n')

if [ "$TABLE_EXISTS" != "yes" ]; then
    echo -e "  ${YELLOW}Database is uninitialized. Running migrations and seeding default accounts...${NC}"
    docker compose exec -u sail laravel.test php artisan migrate:fresh --seed
else
    USER_COUNT=$(docker compose exec -u sail laravel.test php artisan tinker --execute="echo App\Models\User::count();" 2>/dev/null | tr -d '\r\n')
    if [[ -z "$USER_COUNT" || "$USER_COUNT" == "0" ]]; then
        echo -e "  ${YELLOW}Database has tables but no data. Seeding default accounts...${NC}"
        docker compose exec -u sail laravel.test php artisan db:seed
    else
        echo -e "  ${GREEN}✔ Database already populated with $USER_COUNT users. Running pending migrations...${NC}"
        docker compose exec -u sail laravel.test php artisan migrate
    fi
fi
echo ""

# 8. Frontend Assets (NPM dependencies and dev server)
echo -e "${BLUE}[8/8] Processing frontend assets...${NC}"
if [ ! -d node_modules ]; then
    echo -e "  ${YELLOW}Node modules not found. Installing NPM dependencies inside container...${NC}"
    docker compose exec -u sail laravel.test npm install
else
    echo -e "  ${GREEN}✔ Node dependencies are already present.${NC}"
fi

# Ensure storage symlink exists
docker compose exec -u sail laravel.test php artisan storage:link &>/dev/null

# Clean up permissions again in case npm install created any root-owned folders
docker compose exec -u root laravel.test chown -R sail:sail /var/www/html/node_modules /var/www/html/package-lock.json 2>/dev/null

# Build production assets first to ensure page loads immediately
echo -e "  ${YELLOW}Compiling frontend production assets (Vite)...${NC}"
docker compose exec -u sail laravel.test npm run build

# Start Vite live-reload server in background
echo -e "  ${GREEN}✔ Production assets compiled. Launching Vite live-reload server in background...${NC}"
docker compose exec -d -u sail laravel.test npm run dev
echo ""

# Retrieve ports for display
PORT_8000=$(grep "^APP_PORT=" .env | cut -d'=' -f2- | tr -d '"'\''')
if [ -z "$PORT_8000" ]; then
    PORT_8000="8000"
fi

echo -e "${BLUE}======================================================${NC}"
echo -e "${GREEN}     🎉 Biiproject Kit is running fully in Docker! 🎉   ${NC}"
echo -e "${BLUE}======================================================${NC}"
echo -e "👉 ${GREEN}Web Application:${NC}      http://localhost:${PORT_8000}"
echo -e "👉 ${GREEN}Monitoring Dashboard:${NC} http://localhost:${PORT_8000}/system-monitoring"
echo -e "👉 ${GREEN}API Documentation:${NC}    http://localhost:${PORT_8000}/documentation"
echo -e "👉 ${GREEN}Database Port:${NC}        5432 (PostgreSQL)"
echo -e "👉 ${GREEN}Redis Port:${NC}           6379 (Redis)"
echo -e "${BLUE}======================================================${NC}"
echo -e "${YELLOW}To view live logs, run:${NC}   docker compose logs -f"
echo -e "${YELLOW}To stop the stack, run:${NC} docker compose down"
echo -e "${BLUE}======================================================${NC}"
