#!/usr/bin/env bash
# ============================================================
#  Mail Studio セットアップウィザード
#  使い方:  bash scripts/setup.sh
#
#  やること:
#    1. 前提チェック（Node.js / 依存パッケージ）
#    2. Cloudflare ログイン
#    3. Worker 名の設定
#    4. D1 データベース作成 + スキーマ適用
#    5. シークレット登録（画面に表示されません）
#    6. 送信元 / 送信者表示の設定
#    7. デプロイ
#
#  ※ 何度でも実行できます。済んでいる工程はスキップされます。
#  ※ 初期状態は DRY_RUN=true。このウィザードでは実メールは送信されません。
# ============================================================
set -uo pipefail
cd "$(dirname "$0")/.."
ROOT="$(pwd)"

C_G=$'\033[32m'; C_Y=$'\033[33m'; C_R=$'\033[31m'; C_B=$'\033[1m'; C_0=$'\033[0m'
ok()   { printf "%s✅ %s%s\n" "$C_G" "$1" "$C_0"; }
warn() { printf "%s⚠️  %s%s\n" "$C_Y" "$1" "$C_0"; }
err()  { printf "%s❌ %s%s\n" "$C_R" "$1" "$C_0"; }
step() { printf "\n%s━━━ %s ━━━%s\n" "$C_B" "$1" "$C_0"; }
ask()  { # ask "質問" "既定値" → 標準出力に回答
  local q="$1" d="${2:-}" a=""
  if [ -n "$d" ]; then printf "%s [%s]: " "$q" "$d" >&2; else printf "%s: " "$q" >&2; fi
  read -r a </dev/tty
  printf "%s" "${a:-$d}"
}
yesno() { # yesno "質問" → 0=はい
  local a=""
  printf "%s (y/N): " "$1" >&2
  read -r a </dev/tty
  [[ "$a" =~ ^[yY] ]]
}

# wrangler.jsonc のキーを1つ書き換える（コメント付きJSONを壊さないようテキスト置換）
set_wrangler() { # set_wrangler <キー> <値>
  node -e '
    const fs = require("fs");
    const [key, val] = process.argv.slice(1);
    const f = "wrangler.jsonc";
    let s = fs.readFileSync(f, "utf8");
    const re = new RegExp("(\"" + key + "\"\\s*:\\s*)\"[^\"]*\"");
    if (!re.test(s)) { console.error("キーが見つかりません: " + key); process.exit(1); }
    s = s.replace(re, (_m, p1) => p1 + JSON.stringify(val));
    fs.writeFileSync(f, s);
  ' "$1" "$2"
}
get_wrangler() { # get_wrangler <キー> → 値
  node -e '
    const fs = require("fs");
    const s = fs.readFileSync("wrangler.jsonc", "utf8");
    const m = s.match(new RegExp("\"" + process.argv[1] + "\"\\s*:\\s*\"([^\"]*)\""));
    process.stdout.write(m ? m[1] : "");
  ' "$1"
}

cat <<'BANNER'

  ┌────────────────────────────────────────────┐
  │   Mail Studio — セットアップウィザード     │
  │   所要時間: 約5分                          │
  └────────────────────────────────────────────┘

  このウィザードは何度でも実行できます。
  途中でやめたい場合は Ctrl+C で中断してください。

BANNER

# ============ 1. 前提チェック ============
step "1/7  前提チェック"

if ! command -v node >/dev/null 2>&1; then
  err "Node.js が見つかりません。https://nodejs.org/ から 18 以上をインストールしてください"
  exit 1
fi
NODE_MAJOR=$(node -p "process.versions.node.split('.')[0]")
if [ "$NODE_MAJOR" -lt 18 ]; then
  err "Node.js $(node -v) は古すぎます。18 以上にしてください"
  exit 1
fi
ok "Node.js $(node -v)"

if [ ! -d node_modules ]; then
  warn "依存パッケージが未インストールです。npm install を実行します（1〜2分）"
  npm install || { err "npm install に失敗しました"; exit 1; }
fi
ok "依存パッケージ"

# ============ 2. Cloudflare ログイン ============
step "2/7  Cloudflare アカウント"

if npx --no-install wrangler whoami >/dev/null 2>&1; then
  ok "ログイン済み: $(npx --no-install wrangler whoami 2>/dev/null | grep -oE '[^ ]+@[^ ]+' | head -1)"
else
  echo "ブラウザが開きます。Cloudflare にログインして「Allow」を押してください。"
  echo "（Cloudflare アカウントが無い場合は https://dash.cloudflare.com/sign-up で無料登録）"
  echo
  read -r -p "Enter キーでブラウザを開きます..." </dev/tty
  npx wrangler login || { err "ログインに失敗しました"; exit 1; }
  ok "ログイン完了"
fi

# ============ 3. Worker 名 ============
step "3/7  Worker（アプリ）の名前"

CUR_NAME=$(get_wrangler name)
echo "管理画面の URL は  https://＜Worker名＞.＜あなたのID＞.workers.dev  になります。"
echo "半角英数字とハイフンのみ。"
NEW_NAME=$(ask "Worker 名" "$CUR_NAME")
if [[ ! "$NEW_NAME" =~ ^[a-z0-9][a-z0-9-]*$ ]]; then
  err "使えない名前です（半角小文字・数字・ハイフンのみ）"
  exit 1
fi
set_wrangler name "$NEW_NAME" && ok "Worker 名: $NEW_NAME"

# ============ 4. D1 データベース ============
step "4/7  データベース（Cloudflare D1）"

DB_NAME="mail_db"
DB_ID=$(node -e '
  const { execSync } = require("child_process");
  try {
    const out = execSync("npx --no-install wrangler d1 list --json", { stdio: ["ignore","pipe","ignore"] }).toString();
    const list = JSON.parse(out);
    const hit = list.find((d) => d.name === process.argv[1]);
    process.stdout.write(hit ? (hit.uuid || hit.database_id || "") : "");
  } catch { process.stdout.write(""); }
' "$DB_NAME")

if [ -z "$DB_ID" ]; then
  echo "データベース \"$DB_NAME\" を作成します..."
  npx wrangler d1 create "$DB_NAME" >/dev/null 2>&1 || true
  DB_ID=$(node -e '
    const { execSync } = require("child_process");
    try {
      const out = execSync("npx --no-install wrangler d1 list --json", { stdio: ["ignore","pipe","ignore"] }).toString();
      const hit = JSON.parse(out).find((d) => d.name === process.argv[1]);
      process.stdout.write(hit ? (hit.uuid || hit.database_id || "") : "");
    } catch { process.stdout.write(""); }
  ' "$DB_NAME")
fi

if [ -z "$DB_ID" ]; then
  err "D1 データベースの作成に失敗しました。手動で実行してください:"
  echo "    npx wrangler d1 create $DB_NAME"
  echo "  返ってきた database_id を wrangler.jsonc に貼り付けたあと、もう一度このスクリプトを実行してください。"
  exit 1
fi
set_wrangler database_id "$DB_ID"
ok "データベース準備完了（ID は wrangler.jsonc に自動で書き込みました）"

echo "テーブルを作成します（何度実行しても安全です）..."
if npm run --silent db:init:remote >/dev/null 2>&1; then
  ok "テーブル作成完了"
else
  warn "テーブル作成でエラーが出ました。あとで次のコマンドを実行してください:  npm run db:init:remote"
fi

# ============ 5. シークレット ============
step "5/7  パスワードと API キー"

echo "ここで入力する値は画面に表示されず、ファイルにも保存されません。"
echo "Cloudflare の Secrets に直接保管されます。"
echo

EXISTING=$(npx --no-install wrangler secret list 2>/dev/null || echo "")

# --- 管理画面パスワード ---
if echo "$EXISTING" | grep -q "ADMIN_PASSWORD"; then
  ok "ADMIN_PASSWORD は登録済み"
  if yesno "管理画面のパスワードを設定し直しますか？"; then
    npx wrangler secret put ADMIN_PASSWORD </dev/tty && ok "ADMIN_PASSWORD 更新"
  fi
else
  echo "▸ 管理画面のログインパスワードを決めてください（12文字以上を推奨）"
  echo "  ※ 他のサービスと同じパスワードは使わないでください"
  npx wrangler secret put ADMIN_PASSWORD </dev/tty && ok "ADMIN_PASSWORD 登録"
fi

# --- セッション鍵（自動生成） ---
if echo "$EXISTING" | grep -q "SESSION_SECRET"; then
  ok "SESSION_SECRET は登録済み"
else
  echo "▸ セッション鍵を自動生成して登録します（入力不要）"
  GEN=$(node -e "process.stdout.write(require('crypto').randomBytes(32).toString('base64url'))")
  if printf '%s' "$GEN" | npx wrangler secret put SESSION_SECRET >/dev/null 2>&1; then
    ok "SESSION_SECRET 登録（自動生成）"
  else
    warn "自動登録に失敗しました。次のコマンドで手動登録してください:  npx wrangler secret put SESSION_SECRET"
  fi
  unset GEN
fi

# --- Resend APIキー ---
if echo "$EXISTING" | grep -q "RESEND_API_KEY"; then
  ok "RESEND_API_KEY は登録済み"
else
  echo
  echo "▸ Resend の API キー（メール送信サービス）"
  echo "  まだ持っていない場合は https://resend.com/ で無料登録 →"
  echo "  ドメイン追加 → DNS設定 → API Keys から作成できます。"
  echo "  ※ 今は未取得でも構いません。DRY_RUN=true のあいだは不要です。"
  if yesno "いま Resend の API キーを登録しますか？"; then
    npx wrangler secret put RESEND_API_KEY </dev/tty && ok "RESEND_API_KEY 登録"
  else
    warn "スキップしました。あとで:  npx wrangler secret put RESEND_API_KEY"
  fi
fi

# ============ 6. 送信元 / 送信者表示 ============
step "6/7  送信元アドレスと送信者表示"

echo "▸ 送信元アドレス（Resend で認証済みのドメインのアドレス）"
echo "  例: news@example.com"
CUR_FROM=$(get_wrangler MAIL_FROM)
NEW_FROM=$(ask "MAIL_FROM" "$CUR_FROM")
set_wrangler MAIL_FROM "$NEW_FROM"

echo
echo "▸ 送信者表示（特定電子メール法で必須。全メールのフッターに自動挿入されます）"
echo "  氏名または名称 / 住所 / 連絡先 を書いてください。"
echo "  例: 山田太郎 / 〒100-0001 東京都千代田区1-1-1 / info@example.com"
CUR_INFO=$(get_wrangler SENDER_INFO)
NEW_INFO=$(ask "SENDER_INFO" "$CUR_INFO")
set_wrangler SENDER_INFO "$NEW_INFO"
ok "送信設定を保存しました"

if [ "$NEW_INFO" = "あなたの名称 / 住所 / 連絡先" ] || [ -z "$NEW_INFO" ]; then
  warn "SENDER_INFO が未設定です。実送信の前に必ず設定してください（法令上の必須表示です）"
fi

# ============ 7. デプロイ ============
step "7/7  デプロイ"

echo "現在の DRY_RUN は \"$(get_wrangler DRY_RUN)\" です。"
echo "（true のあいだは、どんな操作をしても実メールは1通も送信されません）"
echo
if yesno "デプロイしますか？"; then
  if npm run --silent deploy; then
    ok "デプロイ完了"
  else
    err "デプロイに失敗しました。エラー内容を Claude Code に貼り付けて相談してください"
    exit 1
  fi
else
  warn "スキップしました。あとで:  npm run deploy"
fi

# ============ 完了 ============
cat <<EOF

${C_G}${C_B}━━━━━━━━━━ セットアップ完了 ━━━━━━━━━━${C_0}

  管理画面:  https://${NEW_NAME}.＜あなたのCloudflareのID＞.workers.dev/
             （↑ 上のデプロイログに正確な URL が出ています）
  使い方:    上記URL + /manual/mail-studio/
  ログイン:  さきほど設定した ADMIN_PASSWORD

${C_B}▼ 次にやること${C_0}

  1. 管理画面を開いてログインできるか確認する
  2. Resend でドメインを Verified にする（未実施の場合）
  3. 自分のアドレスだけを入れたリストを作り、テスト配信する
  4. 中身に問題がなければ実送信へ切り替える:

       wrangler.jsonc の "DRY_RUN" を "false" に変更 → npm run deploy

${C_B}▼ 困ったら${C_0}

  このフォルダで  ${C_B}claude${C_0}  と入力して Claude Code に相談してください。
  「セットアップの続きを手伝って」「このエラーを直して」で通じます。
  文書での確認は  SUPPORT.md / セットアップガイド.md  をどうぞ。

EOF
