"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConsoleController = void 0;
const common_1 = require("@nestjs/common");
const config_1 = require("@nestjs/config");
const swagger_1 = require("@nestjs/swagger");
const api_paths_1 = require("../common/api-paths");
const auth_service_1 = require("./auth.service");
const auth_throttle_decorator_1 = require("./auth-throttle.decorator");
const public_decorator_1 = require("./public.decorator");
let ConsoleController = class ConsoleController {
    auth;
    config;
    cookieName = 'smart_estate_console_token';
    constructor(auth, config) {
        this.auth = auth;
        this.config = config;
    }
    loginPage(returnTo = '', phone = '', notice, devOtp, error) {
        const safeReturnTo = this.safeReturnTo(returnTo || this.docsPath());
        const errorBlock = error ? `<div class="error">${this.escape(error)}</div>` : '';
        const noticeBlock = notice ? `<div class="notice">${this.escape(notice)}${devOtp ? ` DEV OTP: ${this.escape(devOtp)}` : ''}</div>` : '';
        return `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Super Admin Console Login</title>
  <style>
    :root { color-scheme: light; --bg: #f6f8fb; --panel: #fff; --ink: #172033; --muted: #607086; --line: #d9e1ec; --accent: #0f766e; --danger: #b42318; }
    * { box-sizing: border-box; }
    body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: var(--bg); color: var(--ink); font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
    main { width: min(420px, calc(100vw - 32px)); background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 24px; }
    h1 { margin: 0 0 8px; font-size: 24px; letter-spacing: 0; }
    p { margin: 0 0 18px; color: var(--muted); line-height: 1.5; }
    label { display: block; margin: 14px 0 6px; font-weight: 700; font-size: 13px; }
    input { width: 100%; border: 1px solid var(--line); border-radius: 6px; padding: 11px 12px; font: inherit; }
    button { width: 100%; margin-top: 18px; border: 0; border-radius: 6px; padding: 12px; font: inherit; font-weight: 800; color: #fff; background: var(--accent); cursor: pointer; }
    .error { margin: 0 0 14px; padding: 10px 12px; border-radius: 6px; color: var(--danger); background: #fff1f0; border: 1px solid #ffd0cc; }
    .notice { margin: 0 0 14px; padding: 10px 12px; border-radius: 6px; color: #0b5f59; background: #ecfdf5; border: 1px solid #b8eadc; }
    .secondary { background: #e8eef6; color: var(--ink); }
  </style>
</head>
<body>
  <main>
    <h1>Super Admin Console</h1>
    <p>Sign in as a super admin to open Swagger docs or the API sandbox.</p>
    ${errorBlock}
    ${noticeBlock}
    <form method="post" action="${this.consolePath('request-otp')}">
      <input type="hidden" name="returnTo" value="${this.escape(safeReturnTo)}" />
      <label for="requestPhone">Phone</label>
      <input id="requestPhone" name="phone" type="tel" autocomplete="username" value="${this.escape(phone)}" placeholder="+2348000000001" required />
      <button class="secondary" type="submit">Send OTP</button>
    </form>
    <form method="post" action="${this.consolePath('login')}">
      <input type="hidden" name="returnTo" value="${this.escape(safeReturnTo)}" />
      <label for="phone">Phone</label>
      <input id="phone" name="phone" type="tel" autocomplete="username" value="${this.escape(phone)}" placeholder="+2348000000001" required />
      <label for="otp">OTP</label>
      <input id="otp" name="otp" inputmode="numeric" autocomplete="one-time-code" placeholder="123456" required />
      <button type="submit">Continue</button>
    </form>
  </main>
</body>
</html>`;
    }
    async requestOtp(body, res) {
        const returnTo = this.safeReturnTo(body.returnTo ?? this.docsPath());
        const phone = body.phone ?? '';
        try {
            const result = await this.auth.requestConsoleOtp(phone);
            const query = new URLSearchParams({
                returnTo,
                phone,
                notice: 'OTP sent'
            });
            if (result.devOtp) {
                query.set('devOtp', result.devOtp);
            }
            return res.redirect(`${this.loginPath()}?${query.toString()}`);
        }
        catch (error) {
            const message = error instanceof Error ? error.message : 'OTP request failed';
            return res.redirect(`${this.loginPath()}?returnTo=${encodeURIComponent(returnTo)}&phone=${encodeURIComponent(phone)}&error=${encodeURIComponent(message)}`);
        }
    }
    async login(body, res) {
        const returnTo = this.safeReturnTo(body.returnTo ?? this.docsPath());
        try {
            const token = await this.auth.issueConsoleSession({
                phone: body.phone ?? '',
                otp: body.otp ?? ''
            });
            res.cookie(this.cookieName, token, {
                httpOnly: true,
                sameSite: 'lax',
                secure: this.config.get('NODE_ENV') === 'production',
                maxAge: this.consoleSessionMaxAge(),
                path: (0, api_paths_1.apiPath)(this.config)
            });
            return res.redirect(returnTo);
        }
        catch (error) {
            const message = error instanceof Error ? error.message : 'Console login failed';
            return res.redirect(`${this.loginPath()}?returnTo=${encodeURIComponent(returnTo)}&error=${encodeURIComponent(message)}`);
        }
    }
    logout(res) {
        res.clearCookie(this.cookieName, { path: (0, api_paths_1.apiPath)(this.config) });
        return res.redirect(this.loginPath());
    }
    safeReturnTo(value) {
        if (!value.startsWith(this.docsPath()) && !value.startsWith((0, api_paths_1.sandboxPath)(this.config))) {
            return this.docsPath();
        }
        return value;
    }
    docsPath() {
        return (0, api_paths_1.docsPath)(this.config);
    }
    loginPath() {
        return (0, api_paths_1.consoleLoginPath)(this.config);
    }
    consolePath(action) {
        return (0, api_paths_1.versionedApiPath)(this.config, 'console', action);
    }
    consoleSessionMaxAge() {
        const ttl = this.config.get('CONSOLE_SESSION_TTL', '8h');
        const hours = ttl.match(/^(\d+)h$/i);
        if (hours) {
            return Number(hours[1]) * 60 * 60 * 1000;
        }
        const seconds = ttl.match(/^(\d+)s$/i);
        if (seconds) {
            return Number(seconds[1]) * 1000;
        }
        return 8 * 60 * 60 * 1000;
    }
    escape(value) {
        return value
            .replaceAll('&', '&amp;')
            .replaceAll('<', '&lt;')
            .replaceAll('>', '&gt;')
            .replaceAll('"', '&quot;')
            .replaceAll("'", '&#039;');
    }
};
exports.ConsoleController = ConsoleController;
__decorate([
    (0, common_1.Get)('login'),
    (0, common_1.Header)('Content-Type', 'text/html; charset=utf-8'),
    __param(0, (0, common_1.Query)('returnTo')),
    __param(1, (0, common_1.Query)('phone')),
    __param(2, (0, common_1.Query)('notice')),
    __param(3, (0, common_1.Query)('devOtp')),
    __param(4, (0, common_1.Query)('error')),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object, String, String, String]),
    __metadata("design:returntype", void 0)
], ConsoleController.prototype, "loginPage", null);
__decorate([
    (0, common_1.Post)('request-otp'),
    (0, auth_throttle_decorator_1.AuthThrottle)(),
    __param(0, (0, common_1.Body)()),
    __param(1, (0, common_1.Res)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object]),
    __metadata("design:returntype", Promise)
], ConsoleController.prototype, "requestOtp", null);
__decorate([
    (0, common_1.Post)('login'),
    (0, auth_throttle_decorator_1.AuthThrottle)(),
    __param(0, (0, common_1.Body)()),
    __param(1, (0, common_1.Res)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object, Object]),
    __metadata("design:returntype", Promise)
], ConsoleController.prototype, "login", null);
__decorate([
    (0, common_1.Post)('logout'),
    __param(0, (0, common_1.Res)()),
    __metadata("design:type", Function),
    __metadata("design:paramtypes", [Object]),
    __metadata("design:returntype", void 0)
], ConsoleController.prototype, "logout", null);
exports.ConsoleController = ConsoleController = __decorate([
    (0, public_decorator_1.Public)(),
    (0, swagger_1.ApiExcludeController)(),
    (0, common_1.Controller)({ path: 'console', version: '1' }),
    __metadata("design:paramtypes", [auth_service_1.AuthService,
        config_1.ConfigService])
], ConsoleController);
//# sourceMappingURL=console.controller.js.map