import * as vscode from 'vscode';
import { ApprovalQueue, Approval } from './approvalQueue';
import { wrapPanelAsView } from '../../sidebarProvider';

/**
 * A small webview view that surfaces the currently pending approval, separate
 * from the chat. The provider is intentionally thin: state lives in
 * ApprovalQueue, this class only renders + relays button clicks.
 *
 * Mirroring the existing sidebar.html + media/ separation pattern would be
 * appropriate once the panel grows, but the current UI is small enough
 * (~40 lines of HTML) that an inline template keeps the diff focused.
 */
export class ApprovalPanelProvider implements vscode.WebviewViewProvider {
    public static readonly viewType = 'g1nation-approval-panel';

    private _view?: vscode.WebviewView;
    private _panel?: vscode.WebviewPanel;
    private _subscription?: vscode.Disposable;

    constructor(
        private readonly _extensionUri: vscode.Uri,
        private readonly _queue: ApprovalQueue
    ) {}

    public resolveWebviewView(view: vscode.WebviewView): void {
        this._initView(view);
    }

    /** Open the approvals UI as an editor panel (Column 3 by default). */
    public openAsPanel(column: vscode.ViewColumn = vscode.ViewColumn.Three): vscode.WebviewPanel {
        if (this._panel) {
            this._panel.reveal(column);
            return this._panel;
        }
        const panel = vscode.window.createWebviewPanel(
            ApprovalPanelProvider.viewType,
            'Pending Approvals',
            column,
            { enableScripts: true, localResourceRoots: [this._extensionUri], retainContextWhenHidden: true }
        );
        this._panel = panel;
        const adapter = wrapPanelAsView(panel);
        panel.onDidDispose(() => {
            if (this._panel === panel) this._panel = undefined;
            if (this._view === adapter) this._view = undefined;
        });
        this._initView(adapter);
        return panel;
    }

    private _initView(view: vscode.WebviewView): void {
        this._view = view;
        view.webview.options = { enableScripts: true, localResourceRoots: [this._extensionUri] };
        view.webview.html = this._render(this._queue.current());

        view.webview.onDidReceiveMessage((msg: { type: string; id?: string }) => {
            if (msg?.type === 'approve') void this._queue.approve(msg.id);
            else if (msg?.type === 'reject') void this._queue.reject(msg.id);
            else if (msg?.type === 'refresh') view.webview.html = this._render(this._queue.current());
        });

        this._subscription?.dispose();
        this._subscription = this._queue.onChange(() => {
            if (this._view) this._view.webview.html = this._render(this._queue.current());
        });

        view.onDidDispose(() => {
            this._subscription?.dispose();
            this._subscription = undefined;
            if (this._view === view) this._view = undefined;
        });
    }

    /** Bring the panel into focus; used by the status bar badge. */
    public focus(): void {
        if (this._panel) {
            this._panel.reveal(this._panel.viewColumn ?? vscode.ViewColumn.Three);
            return;
        }
        this.openAsPanel();
    }

    private _render(approval: Approval | null): string {
        const csp = `default-src 'none'; style-src 'unsafe-inline'; script-src 'unsafe-inline';`;
        const empty = !approval;
        const body = empty ? this._renderEmpty() : this._renderApproval(approval as Approval);
        return `<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="${csp}">
    <style>
        body { font-family: var(--vscode-font-family); font-size: 12px; padding: 12px; color: var(--vscode-foreground); }
        .empty { color: var(--vscode-descriptionForeground); padding: 24px 8px; text-align: center; }
        .card { border: 1px solid var(--vscode-panel-border); border-radius: 6px; padding: 12px; margin-bottom: 8px; background: var(--vscode-editor-background); }
        .title { font-weight: 600; margin-bottom: 4px; }
        .summary { color: var(--vscode-descriptionForeground); margin-bottom: 8px; font-size: 11px; }
        .files { margin: 8px 0; padding: 6px 8px; background: var(--vscode-textCodeBlock-background); border-radius: 4px; max-height: 160px; overflow-y: auto; }
        .files li { font-family: var(--vscode-editor-font-family); font-size: 11px; line-height: 1.6; word-break: break-all; list-style: none; }
        .files .badge { display: inline-block; min-width: 56px; padding: 1px 6px; border-radius: 3px; font-size: 10px; margin-right: 6px; text-align: center; background: var(--vscode-badge-background); color: var(--vscode-badge-foreground); }
        .actions { display: flex; gap: 6px; margin-top: 10px; }
        button { flex: 1; padding: 6px 10px; border: 1px solid var(--vscode-button-border, transparent); border-radius: 4px; cursor: pointer; font-size: 12px; }
        button.approve { background: var(--vscode-button-background); color: var(--vscode-button-foreground); }
        button.approve:hover { background: var(--vscode-button-hoverBackground); }
        button.reject { background: var(--vscode-button-secondaryBackground); color: var(--vscode-button-secondaryForeground); }
        button.reject:hover { background: var(--vscode-button-secondaryHoverBackground); }
    </style>
</head>
<body>
    ${body}
    <script>
        const vscode = acquireVsCodeApi();
        for (const btn of document.querySelectorAll('button[data-action]')) {
            btn.addEventListener('click', () => {
                vscode.postMessage({ type: btn.dataset.action, id: btn.dataset.id });
            });
        }
    </script>
</body>
</html>`;
    }

    private _renderEmpty(): string {
        return `<div class="empty">대기 중인 승인이 없습니다.</div>`;
    }

    private _renderApproval(a: Approval): string {
        const filesHtml = a.files.length === 0
            ? '<li style="color: var(--vscode-descriptionForeground);">파일 변경 없음</li>'
            : a.files.map(f => `<li><span class="badge">변경</span>${this._escape(f)}</li>`).join('');
        const elapsed = Math.max(0, Math.floor((Date.now() - a.createdAt) / 1000));
        return `
            <div class="card">
                <div class="title">${this._escape(a.title)}</div>
                <div class="summary">${this._escape(a.summary)} · ${elapsed}초 전</div>
                <ul class="files">${filesHtml}</ul>
                <div class="actions">
                    <button class="approve" data-action="approve" data-id="${this._escape(a.id)}">승인</button>
                    <button class="reject" data-action="reject" data-id="${this._escape(a.id)}">거부</button>
                </div>
            </div>`;
    }

    private _escape(s: string): string {
        return String(s).replace(/[&<>"']/g, ch => (
            ch === '&' ? '&amp;' :
            ch === '<' ? '&lt;' :
            ch === '>' ? '&gt;' :
            ch === '"' ? '&quot;' : '&#39;'
        ));
    }
}
