#!/bin/bash

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

BACKEND_MAX_RETRIES="${BACKEND_MAX_RETRIES:-3}"
BACKEND_HEALTH_CHECK_ATTEMPTS="${BACKEND_HEALTH_CHECK_ATTEMPTS:-10}"
BACKEND_HEALTH_CHECK_INTERVAL="${BACKEND_HEALTH_CHECK_INTERVAL:-2}"
FRONTEND_MAX_RETRIES="${FRONTEND_MAX_RETRIES:-3}"
FRONTEND_HEALTH_CHECK_ATTEMPTS="${FRONTEND_HEALTH_CHECK_ATTEMPTS:-10}"
FRONTEND_HEALTH_CHECK_INTERVAL="${FRONTEND_HEALTH_CHECK_INTERVAL:-2}"
DEFAULT_BACKEND_PORT="${DEFAULT_BACKEND_PORT:-8000}"
DEFAULT_FRONTEND_PORT="${DEFAULT_FRONTEND_PORT:-3000}"

ensure_uv_backend_deps() {
    echo -e "${BLUE}📦 检查后端 uv 环境...${NC}"

    if ! command -v uv >/dev/null 2>&1; then
        echo -e "${RED}❌ 未找到 uv，请先安装 uv 并加入 PATH${NC}"
        exit 1
    fi

    cd "$SCRIPT_DIR"

    if [ ! -x "$SCRIPT_DIR/.venv/bin/python" ]; then
        echo -e "${YELLOW}⚠️  未检测到 .venv，正在执行 uv sync...${NC}"
        uv sync --group dev
    fi

    if [ ! -x "$SCRIPT_DIR/.venv/bin/python" ]; then
        echo -e "${RED}❌ uv 环境初始化失败，未找到 .venv/bin/python${NC}"
        exit 1
    fi
}

ensure_frontend_deps() {
    echo -e "${BLUE}📦 检查前端依赖...${NC}"

    if ! command -v bun >/dev/null 2>&1; then
        echo -e "${RED}❌ 未找到 bun，请先安装或加载 bun 到 PATH${NC}"
        exit 1
    fi

    cd "$SCRIPT_DIR/frontend"

    if [ ! -x "$SCRIPT_DIR/frontend/node_modules/.bin/vite" ]; then
        echo -e "${YELLOW}⚠️  前端依赖缺失，正在执行 bun install...${NC}"
        bun install
    fi

    if [ ! -x "$SCRIPT_DIR/frontend/node_modules/.bin/vite" ]; then
        echo -e "${RED}❌ 前端依赖安装失败，未找到 vite${NC}"
        exit 1
    fi
}

wait_for_http() {
    local url="$1"
    local attempts="$2"
    local interval="$3"
    local service_name="$4"
    local attempt=1

    while [ "$attempt" -le "$attempts" ]; do
        if curl -s "$url" > /dev/null 2>&1; then
            return 0
        fi

        echo -e "${YELLOW}⏳ 等待${service_name}就绪 (${attempt}/${attempts})...${NC}"
        sleep "$interval"
        attempt=$((attempt + 1))
    done

    return 1
}

start_backend_with_retry() {
    local backend_port="$1"
    local retry=1

    while [ "$retry" -le "$BACKEND_MAX_RETRIES" ]; do
        pkill -f "uvicorn" 2>/dev/null || true
        cd "$SCRIPT_DIR/backend"
        PYTHONPATH="$SCRIPT_DIR/backend" nohup uv run --project "$SCRIPT_DIR" python -m uvicorn app.main:app --host 0.0.0.0 --port "$backend_port" --reload > /tmp/planet_backend.log 2>&1 &
        BACKEND_PID=$!

        if wait_for_http "http://localhost:${backend_port}/health" "$BACKEND_HEALTH_CHECK_ATTEMPTS" "$BACKEND_HEALTH_CHECK_INTERVAL" "后端"; then
            return 0
        fi

        echo -e "${YELLOW}⚠️  后端第 ${retry}/${BACKEND_MAX_RETRIES} 次启动未就绪，准备重试...${NC}"
        kill "$BACKEND_PID" 2>/dev/null || true
        retry=$((retry + 1))
    done

    return 1
}

start_frontend_with_retry() {
    local frontend_port="$1"
    local retry=1

    while [ "$retry" -le "$FRONTEND_MAX_RETRIES" ]; do
        pkill -f "vite" 2>/dev/null || true
        pkill -f "bun run dev" 2>/dev/null || true
        cd "$SCRIPT_DIR/frontend"
        nohup bun run dev --port "$frontend_port" > /tmp/planet_frontend.log 2>&1 &
        FRONTEND_PID=$!

        if wait_for_http "http://localhost:${frontend_port}" "$FRONTEND_HEALTH_CHECK_ATTEMPTS" "$FRONTEND_HEALTH_CHECK_INTERVAL" "前端"; then
            return 0
        fi

        echo -e "${YELLOW}⚠️  前端第 ${retry}/${FRONTEND_MAX_RETRIES} 次启动未就绪，准备重试...${NC}"
        kill "$FRONTEND_PID" 2>/dev/null || true
        retry=$((retry + 1))
    done

    return 1
}

validate_port() {
    local port="$1"

    if ! [[ "$port" =~ ^[0-9]+$ ]] || [ "$port" -lt 1 ] || [ "$port" -gt 65535 ]; then
        echo -e "${RED}❌ 非法端口: ${port}${NC}"
        exit 1
    fi
}

kill_port_if_requested() {
    local port="$1"
    local service_name="$2"

    echo -e "${YELLOW}🧹 检测 ${service_name} 端口 ${port} 占用...${NC}"

    if command -v fuser >/dev/null 2>&1 && fuser "${port}/tcp" >/dev/null 2>&1; then
        echo -e "${BLUE}🔌 发现端口 ${port} 占用，正在终止...${NC}"
        fuser -k "${port}/tcp" >/dev/null 2>&1 || true
        sleep 1
        return 0
    fi

    if command -v lsof >/dev/null 2>&1; then
        local pids
        pids="$(lsof -ti tcp:"${port}" 2>/dev/null || true)"
        if [ -n "$pids" ]; then
            echo -e "${BLUE}🔌 发现端口 ${port} 占用，正在终止...${NC}"
            kill $pids 2>/dev/null || true
            sleep 1
            return 0
        fi
    fi

    echo -e "${GREEN}✅ 端口 ${port} 未被占用${NC}"
}

parse_service_args() {
    BACKEND_PORT="$DEFAULT_BACKEND_PORT"
    FRONTEND_PORT="$DEFAULT_FRONTEND_PORT"
    BACKEND_PORT_REQUESTED=0
    FRONTEND_PORT_REQUESTED=0

    while [ "$#" -gt 0 ]; do
        case "$1" in
            -b|--backend-port)
                BACKEND_PORT_REQUESTED=1
                if [ -n "$2" ] && [[ "$2" =~ ^[0-9]+$ ]]; then
                    BACKEND_PORT="$2"
                    shift 2
                else
                    shift 1
                fi
                ;;
            -f|--frontend-port)
                FRONTEND_PORT_REQUESTED=1
                if [ -n "$2" ] && [[ "$2" =~ ^[0-9]+$ ]]; then
                    FRONTEND_PORT="$2"
                    shift 2
                else
                    shift 1
                fi
                ;;
            *)
                echo -e "${RED}❌ 未知参数: $1${NC}"
                exit 1
                ;;
        esac
    done

    validate_port "$BACKEND_PORT"
    validate_port "$FRONTEND_PORT"
}

cleanup_exit_containers() {
    local exit_containers
    exit_containers="$(docker ps -a --filter status=exited -q 2>/dev/null || true)"
    if [ -n "$exit_containers" ]; then
        echo -e "${BLUE}🗑️  清理残留 Exit 容器...${NC}"
        echo "$exit_containers" | xargs -r docker rm -f >/dev/null 2>&1 || true
        echo -e "${GREEN}✅ 残留容器已清理${NC}"
    fi
}

stop_backend_service() {
    pkill -f "uvicorn" 2>/dev/null || true
}

stop_frontend_service() {
    pkill -f "vite" 2>/dev/null || true
    pkill -f "bun run dev" 2>/dev/null || true
}

start_backend_service() {
    local backend_port="$1"
    local backend_port_requested="$2"

    echo -e "${BLUE}🗄️  启动数据库...${NC}"
    docker start planet_postgres planet_redis 2>/dev/null || docker-compose up -d postgres redis
    sleep 3

    if [ "$backend_port_requested" -eq 1 ]; then
        kill_port_if_requested "$backend_port" "后端"
    fi

    echo -e "${BLUE}🔧 启动后端...${NC}"
    ensure_uv_backend_deps
    if ! start_backend_with_retry "$backend_port"; then
        echo -e "${RED}❌ 后端启动失败，已重试 ${BACKEND_MAX_RETRIES} 次${NC}"
        tail -10 /tmp/planet_backend.log
        exit 1
    fi
}

start_frontend_service() {
    local frontend_port="$1"
    local frontend_port_requested="$2"

    if [ "$frontend_port_requested" -eq 1 ]; then
        kill_port_if_requested "$frontend_port" "前端"
    fi

    echo -e "${BLUE}🌐 启动前端...${NC}"
    ensure_frontend_deps
    if ! start_frontend_with_retry "$frontend_port"; then
        echo -e "${RED}❌ 前端启动失败，已重试 ${FRONTEND_MAX_RETRIES} 次${NC}"
        tail -10 /tmp/planet_frontend.log
        exit 1
    fi
}

create_user() {
    local username
    local password
    local password_confirm
    local email
    local generated_email
    local role="viewer"
    local is_admin

    ensure_uv_backend_deps

    echo -e "${BLUE}🗄️  启动数据库...${NC}"
    docker start planet_postgres 2>/dev/null || docker-compose up -d postgres
    sleep 2

    echo -e "${BLUE}👤 创建用户${NC}"
    read -r -p "用户名: " username

    if [ -z "$username" ]; then
        echo -e "${RED}❌ 用户名不能为空${NC}"
        exit 1
    fi

    generated_email="${username}@planet.local"
    read -r -p "邮箱(留空自动使用 ${generated_email}): " email
    if [ -z "$email" ]; then
        email="$generated_email"
    fi

    read -r -s -p "密码: " password
    echo ""
    read -r -s -p "确认密码: " password_confirm
    echo ""

    if [ -z "$password" ]; then
        echo -e "${RED}❌ 密码不能为空${NC}"
        exit 1
    fi

    if [ "${#password}" -lt 8 ]; then
        echo -e "${RED}❌ 密码长度不能少于 8 位${NC}"
        exit 1
    fi

    if [ "$password" != "$password_confirm" ]; then
        echo -e "${RED}❌ 两次输入的密码不一致${NC}"
        exit 1
    fi

    read -r -p "是否为管理员? (Y/N): " is_admin
    if [[ "$is_admin" =~ ^[Yy]$ ]]; then
        role="super_admin"
    fi

    cd "$SCRIPT_DIR/backend"
    PLANET_CREATEUSER_USERNAME="$username" \
    PLANET_CREATEUSER_PASSWORD="$password" \
    PLANET_CREATEUSER_EMAIL="$email" \
    PLANET_CREATEUSER_ROLE="$role" \
    PYTHONPATH="$SCRIPT_DIR/backend" \
    "$SCRIPT_DIR/.venv/bin/python" - <<'PY'
import asyncio
import os

from sqlalchemy import text

from app.core.security import get_password_hash
from app.db.session import async_session_factory
from app.models.user import User


async def main():
    username = os.environ["PLANET_CREATEUSER_USERNAME"].strip()
    password = os.environ["PLANET_CREATEUSER_PASSWORD"]
    email = os.environ["PLANET_CREATEUSER_EMAIL"].strip()
    role = os.environ["PLANET_CREATEUSER_ROLE"].strip()

    async with async_session_factory() as session:
        result = await session.execute(
            text("SELECT id FROM users WHERE username = :username OR email = :email"),
            {"username": username, "email": email},
        )
        if result.fetchone():
            raise SystemExit("用户名已存在")

        user = User(
            username=username,
            email=email,
            password_hash=get_password_hash(password),
            role=role,
            is_active=True,
        )
        session.add(user)
        await session.commit()


asyncio.run(main())
PY

    echo -e "${GREEN}✅ 用户创建成功${NC}"
    echo "   用户名: ${username}"
    echo "   角色: ${role}"
    echo "   邮箱: ${email}"
}

start() {
    parse_service_args "$@"
    cleanup_exit_containers

    echo -e "${BLUE}🚀 启动智能星球计划...${NC}"

    start_backend_service "$BACKEND_PORT" "$BACKEND_PORT_REQUESTED"
    start_frontend_service "$FRONTEND_PORT" "$FRONTEND_PORT_REQUESTED"

    echo ""
    echo -e "${GREEN}✅ 启动完成!${NC}"
    echo "   前端: http://localhost:${FRONTEND_PORT}"
    echo "   后端: http://localhost:${BACKEND_PORT}"
}

stop() {
    echo -e "${YELLOW}🛑 停止服务...${NC}"
    stop_backend_service
    stop_frontend_service
    docker stop planet_postgres planet_redis 2>/dev/null || true
    echo -e "${GREEN}✅ 已停止${NC}"
}

restart() {
    parse_service_args "$@"
    cleanup_exit_containers

    if [ "$BACKEND_PORT_REQUESTED" -eq 0 ] && [ "$FRONTEND_PORT_REQUESTED" -eq 0 ]; then
        stop
        sleep 1
        start
        return 0
    fi

    echo -e "${YELLOW}🔄 按需重启服务...${NC}"

    if [ "$BACKEND_PORT_REQUESTED" -eq 1 ]; then
        stop_backend_service
        sleep 1
        start_backend_service "$BACKEND_PORT" 1
    fi

    if [ "$FRONTEND_PORT_REQUESTED" -eq 1 ]; then
        stop_frontend_service
        sleep 1
        start_frontend_service "$FRONTEND_PORT" 1
    fi

    echo ""
    echo -e "${GREEN}✅ 重启完成!${NC}"
    if [ "$BACKEND_PORT_REQUESTED" -eq 1 ]; then
        echo "   后端: http://localhost:${BACKEND_PORT}"
    fi
    if [ "$FRONTEND_PORT_REQUESTED" -eq 1 ]; then
        echo "   前端: http://localhost:${FRONTEND_PORT}"
    fi
}

health() {
    echo "📊 容器状态:"
    docker ps --filter "name=planet_" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

    echo ""
    echo "🔍 服务状态:"
    if curl -s http://localhost:8000/health > /dev/null 2>&1; then
        echo -e "  后端: ${GREEN}✅ 运行中${NC}"
    else
        echo -e "  后端: ${RED}❌ 未运行${NC}"
    fi

    if curl -s http://localhost:3000 > /dev/null 2>&1; then
        echo -e "  前端: ${GREEN}✅ 运行中${NC}"
    else
        echo -e "  前端: ${RED}❌ 未运行${NC}"
    fi
}

log() {
    case "$1" in
        -f|--frontend)
            echo "📝 前端日志 (Ctrl+C 退出):"
            tail -f /tmp/planet_frontend.log
            ;;
        -b|--backend)
            echo "📝 后端日志 (Ctrl+C 退出):"
            tail -f /tmp/planet_backend.log
            ;;
        *)
            echo "📝 最近日志:"
            echo "--- 后端 ---"
            tail -20 /tmp/planet_backend.log 2>/dev/null || echo "无日志"
            echo "--- 前端 ---"
            tail -20 /tmp/planet_frontend.log 2>/dev/null || echo "无日志"
            ;;
    esac
}

case "$1" in
    start)
        shift
        start "$@"
        ;;
    stop)
        stop
        ;;
    restart)
        shift
        restart "$@"
        ;;
    createuser)
        create_user
        ;;
    health)
        health
        ;;
    log)
        log "$2"
        ;;
    *)
        echo "用法: ./planet.sh {start|stop|restart|createuser|health|log}"
        echo ""
        echo "命令:"
        echo "  start      启动服务，可选: -b <后端端口> -f <前端端口>"
        echo "  stop       停止服务"
        echo "  restart    重启服务，可选: -b [后端端口] -f [前端端口]"
        echo "  createuser 交互创建用户"
        echo "  health     检查健康状态"
        echo "  log        查看日志"
        echo "  log -f     查看前端日志"
        echo "  log -b     查看后端日志"
        ;;
esac
