import { Hono } from 'hono';
import { PASSWORD_META_KEY } from '../constants';
import { SESSION_MAX_AGE_MS } from '../constants';
import { checkAppPassword } from '../crypto/password';
import {
  clearSessionCookieHeaderForRequest,
  createSessionToken,
  sessionCookieHeaderForRequest,
} from '../middleware/session';

const MAX_AGE_SEC = Math.floor(SESSION_MAX_AGE_MS / 1000);

/** 挂载在 /api/auth 下，路径为 /login、/logout */
export function registerAuthRoutes(apiAuth: Hono<{ Bindings: Env }>): void {
  apiAuth.post('/login', async (c) => {
    const sec = c.env.SESSION_SECRET;
    if (typeof sec !== 'string' || sec.trim().length < 8) {
      return c.json(
        {
          error:
            '服务器未配置 SESSION_SECRET（本地在项目根目录添加 .dev.vars；生产环境执行 wrangler secret put SESSION_SECRET）',
        },
        503,
      );
    }

    let body: { password?: string };
    try {
      body = await c.req.json();
    } catch {
      return c.json({ error: '无效的 JSON' }, 400);
    }
    const password = typeof body.password === 'string' ? body.password : '';

    try {
      const row = await c.env.DB.prepare(
        'SELECT value FROM app_meta WHERE key = ?',
      )
        .bind(PASSWORD_META_KEY)
        .first<{ value: string }>();

      const result = await checkAppPassword(password, row);
      if (!result.ok) {
        return c.json({ error: '密码错误' }, 401);
      }
      if (result.newHashToStore) {
        await c.env.DB.prepare(
          'INSERT OR REPLACE INTO app_meta (key, value) VALUES (?, ?)',
        )
          .bind(PASSWORD_META_KEY, result.newHashToStore)
          .run();
      }
      const token = await createSessionToken(sec.trim());
      c.header(
        'Set-Cookie',
        sessionCookieHeaderForRequest(token, MAX_AGE_SEC, c.req.url),
      );
      return c.json({ ok: true });
    } catch (e) {
      const msg =
        e instanceof Error
          ? e.message
          : typeof e === 'string'
            ? e
            : '登录失败';
      console.error('[sprout2fa] login', e);
      return c.json(
        {
          error: `数据库或运行时错误：${msg}。若提示 no such table，请执行：wrangler d1 migrations apply sprout2fa --local（本地）或加 --remote（线上库）。`,
        },
        500,
      );
    }
  });

  apiAuth.post('/logout', (c) => {
    c.header('Set-Cookie', clearSessionCookieHeaderForRequest(c.req.url));
    return c.json({ ok: true });
  });
}
