using System.Drawing.Drawing2D;
using System.Text.Json;

namespace AxKeyEncryptor;

/// <summary>
/// AX Copilot — Settings Encryptor (개발자 전용)
/// Ollama / vLLM / Gemini 3종 서비스에 대한 설정값 암호화 UI
/// </summary>
public class MainForm : Form
{
    // ── 색상 테마 ───────────────────────────────────────────────────
    private static readonly Color BgDark      = Color.FromArgb(24, 24, 32);
    private static readonly Color BgPanel     = Color.FromArgb(32, 34, 46);
    private static readonly Color BgCard      = Color.FromArgb(42, 44, 58);
    private static readonly Color BgInput     = Color.FromArgb(52, 54, 70);
    private static readonly Color AccentBlue  = Color.FromArgb(88, 130, 255);
    private static readonly Color AccentGreen = Color.FromArgb(80, 200, 120);
    private static readonly Color AccentOrange= Color.FromArgb(255, 160, 60);
    private static readonly Color AccentRed   = Color.FromArgb(255, 90, 90);
    private static readonly Color TextPrimary = Color.FromArgb(230, 232, 240);
    private static readonly Color TextSecondary= Color.FromArgb(140, 145, 170);
    private static readonly Color BorderColor = Color.FromArgb(60, 64, 80);

    // ── 서비스별 탭 컨트롤 ──────────────────────────────────────────
    private TabControl _tabs = null!;

    // Ollama 탭 컨트롤
    private TextBox _ollamaEndpoint = null!;
    private TextBox _ollamaModel = null!;
    private TextBox _ollamaEncEndpoint = null!;
    private TextBox _ollamaEncModel = null!;

    // vLLM 탭 컨트롤
    private TextBox _vllmEndpoint = null!;
    private TextBox _vllmModel = null!;
    private TextBox _vllmApiKey = null!;
    private TextBox _vllmEncEndpoint = null!;
    private TextBox _vllmEncModel = null!;
    private TextBox _vllmEncApiKey = null!;

    // Gemini 탭 컨트롤
    private TextBox _geminiApiKey = null!;
    private TextBox _geminiModel = null!;
    private TextBox _geminiEncApiKey = null!;
    private TextBox _geminiEncModel = null!;

    // 하단 공용
    private RichTextBox _outputBox = null!;
    private TextBox _decryptInput = null!;
    private TextBox _decryptResult = null!;

    public MainForm()
    {
        InitializeComponent();
    }

    private void InitializeComponent()
    {
        // ── 폼 기본 설정 ────────────────────────────────────────
        Text = "AX Copilot — Settings Encryptor";
        Size = new Size(760, 680);
        MinimumSize = new Size(720, 620);
        StartPosition = FormStartPosition.CenterScreen;
        BackColor = BgDark;
        ForeColor = TextPrimary;
        Font = new Font("Segoe UI", 9.5f, FontStyle.Regular);
        FormBorderStyle = FormBorderStyle.FixedSingle;
        MaximizeBox = false;

        // 아이콘 설정
        try
        {
            var asm = System.Reflection.Assembly.GetExecutingAssembly();
            var stream = asm.GetManifestResourceStream("AxKeyEncryptor.Resources.icon.ico");
            if (stream != null) Icon = new Icon(stream);
        }
        catch { }

        // ── 헤더 패널 ──────────────────────────────────────────
        var headerPanel = new Panel
        {
            Dock = DockStyle.Top,
            Height = 60,
            BackColor = Color.Transparent
        };
        headerPanel.Paint += (s, e) =>
        {
            using var brush = new LinearGradientBrush(
                headerPanel.ClientRectangle,
                Color.FromArgb(35, 40, 65),
                Color.FromArgb(24, 24, 32),
                LinearGradientMode.Vertical);
            e.Graphics.FillRectangle(brush, headerPanel.ClientRectangle);

            // 타이틀
            using var titleFont = new Font("Segoe UI", 14f, FontStyle.Bold);
            e.Graphics.DrawString("🔐  AX Copilot — Settings Encryptor",
                titleFont, new SolidBrush(TextPrimary), 20, 8);

            // 서브타이틀
            using var subFont = new Font("Segoe UI", 8.5f, FontStyle.Regular);
            e.Graphics.DrawString("AES-256-CBC 앱 공용 키 암호화 · 모든 PC에서 동일 복호화 · 개발자 전용",
                subFont, new SolidBrush(TextSecondary), 48, 36);
        };
        Controls.Add(headerPanel);

        // ── 메인 컨텐츠 패널 ────────────────────────────────────
        var mainPanel = new Panel
        {
            Dock = DockStyle.Fill,
            Padding = new Padding(16, 8, 16, 16),
            BackColor = BgDark
        };
        Controls.Add(mainPanel);

        // ── 서비스 선택 탭 ──────────────────────────────────────
        _tabs = new TabControl
        {
            Dock = DockStyle.Top,
            Height = 260,
            Font = new Font("Segoe UI", 10f, FontStyle.Regular),
            Padding = new Point(12, 6)
        };
        _tabs.DrawMode = TabDrawMode.OwnerDrawFixed;
        _tabs.DrawItem += DrawTab;
        _tabs.SizeMode = TabSizeMode.Fixed;
        _tabs.ItemSize = new Size(160, 36);

        // Ollama 탭
        var ollamaPage = CreateTabPage("🟢  Ollama", AccentGreen);
        BuildOllamaTab(ollamaPage);
        _tabs.TabPages.Add(ollamaPage);

        // vLLM 탭
        var vllmPage = CreateTabPage("🔵  vLLM (OpenAI)", AccentBlue);
        BuildVllmTab(vllmPage);
        _tabs.TabPages.Add(vllmPage);

        // Gemini 탭
        var geminiPage = CreateTabPage("🟠  Gemini", AccentOrange);
        BuildGeminiTab(geminiPage);
        _tabs.TabPages.Add(geminiPage);

        // 복호화 검증 탭 추가
        var toolsPage = CreateTabPage("🔓  복호화 검증", AccentBlue);
        BuildToolsTab(toolsPage);
        _tabs.TabPages.Add(toolsPage);

        mainPanel.Controls.Add(_tabs);

        // ── 출력 로그 섹션 ──────────────────────────────────────
        var outputLabel = CreateLabel("📋  출력 로그", 10f, FontStyle.Bold);
        outputLabel.Dock = DockStyle.Top;
        outputLabel.Height = 28;
        outputLabel.Padding = new Padding(4, 8, 0, 0);
        mainPanel.Controls.Add(outputLabel);

        _outputBox = new RichTextBox
        {
            Dock = DockStyle.Fill,
            BackColor = Color.FromArgb(18, 18, 24),
            ForeColor = TextPrimary,
            Font = new Font("Cascadia Code", 9.5f, FontStyle.Regular, GraphicsUnit.Point, 0,
                            // fallback if Cascadia Code not installed
                            false),
            BorderStyle = BorderStyle.None,
            ReadOnly = true,
            WordWrap = true,
            Padding = new Padding(8)
        };
        // Cascadia Code fallback
        if (_outputBox.Font.Name != "Cascadia Code")
            _outputBox.Font = new Font("Consolas", 9.5f);
        mainPanel.Controls.Add(_outputBox);

        // ── 하단 상태바 ─────────────────────────────────────────
        var statusBar = new Panel
        {
            Dock = DockStyle.Bottom,
            Height = 30,
            BackColor = Color.FromArgb(20, 22, 30)
        };
        var statusLabel = CreateLabel("   AES-256-CBC  ·  PBKDF2 100K iterations  ·  모든 PC에서 동일한 암호화 키", 8f, FontStyle.Regular);
        statusLabel.ForeColor = TextSecondary;
        statusLabel.Dock = DockStyle.Fill;
        statusLabel.TextAlign = ContentAlignment.MiddleLeft;
        statusBar.Controls.Add(statusLabel);
        Controls.Add(statusBar);

        // ── 컨트롤 순서 (뒤에서 앞으로) ──────────────────────────
        // Panel DockStyle 순서 보장
        Controls.SetChildIndex(statusBar, 0);
        Controls.SetChildIndex(headerPanel, 0);

        mainPanel.Controls.SetChildIndex(_outputBox, 0);
        mainPanel.Controls.SetChildIndex(outputLabel, 0);
        mainPanel.Controls.SetChildIndex(_tabs, 0);

        AppendLog("AX Copilot Settings Encryptor 시작됨", AccentGreen);
        AppendLog("", TextSecondary);
        AppendLog("── 사용 방법 ──────────────────────────────────────────", AccentBlue);
        AppendLog("1. 상단 탭에서 LLM 서비스(Ollama/vLLM/Gemini)를 선택합니다.", TextPrimary);
        AppendLog("2. 각 필드에 평문 값(URL, 모델명, API 키)을 입력합니다.", TextPrimary);
        AppendLog("3. [⚡ 전체 암호화] 버튼으로 모든 필드를 한번에 암호화합니다.", TextPrimary);
        AppendLog("4. [📋 settings.json 복사] 버튼으로 암호화된 JSON을 클립보드에 복사합니다.", TextPrimary);
        AppendLog("5. 복사된 JSON을 settings.json 파일의 llm 섹션에 붙여넣으면 완료!", TextPrimary);
        AppendLog("", TextSecondary);
        AppendLog("── 암호화 방식 ────────────────────────────────────────", AccentBlue);
        AppendLog("• AES-256-CBC + PBKDF2(100K iterations, SHA256)", TextSecondary);
        AppendLog("• 앱 공용 키 방식 — 모든 PC에서 동일한 키로 복호화됩니다.", TextSecondary);
        AppendLog("• 배포 시 settings.json에 암호화된 값을 넣으면 앱이 자동 복호화합니다.", TextSecondary);
        AppendLog("", TextSecondary);
    }

    // ═════════════════════════════════════════════════════════════════
    // Ollama 탭 빌드
    // ═════════════════════════════════════════════════════════════════
    private void BuildOllamaTab(TabPage page)
    {
        int y = 12;
        var desc = CreateLabel("Ollama는 로컬 LLM 서버입니다. API 키가 필요 없습니다.", 9f, FontStyle.Italic);
        desc.ForeColor = TextSecondary;
        desc.Location = new Point(12, y);
        desc.AutoSize = true;
        page.Controls.Add(desc);
        y += 30;

        // Endpoint
        AddFieldPair(page, ref y, "Endpoint URL:", "http://localhost:11434",
            out _ollamaEndpoint, out _ollamaEncEndpoint, "암호화", AccentGreen, (s, e) =>
            {
                EncryptAndShow(_ollamaEndpoint, _ollamaEncEndpoint, "Ollama Endpoint");
            });

        // Model
        AddFieldPair(page, ref y, "Model:", "llama3.1:8b",
            out _ollamaModel, out _ollamaEncModel, "암호화", AccentGreen, (s, e) =>
            {
                EncryptAndShow(_ollamaModel, _ollamaEncModel, "Ollama Model");
            });

        // 전체 암호화 버튼
        var btnAll = CreateButton("⚡ 전체 암호화", AccentGreen);
        btnAll.Location = new Point(12, y + 4);
        btnAll.Size = new Size(130, 34);
        btnAll.Click += (s, e) =>
        {
            EncryptAndShow(_ollamaEndpoint, _ollamaEncEndpoint, "Ollama Endpoint");
            EncryptAndShow(_ollamaModel, _ollamaEncModel, "Ollama Model");
            AppendLog("[Ollama] 전체 암호화 완료 ✔", AccentGreen);
        };
        page.Controls.Add(btnAll);

        // JSON 생성 버튼
        var btnJson = CreateButton("📋  settings.json 복사", AccentGreen);
        btnJson.Location = new Point(150, y + 4);
        btnJson.Size = new Size(200, 34);
        btnJson.Click += (s, e) => GenerateOllamaJson();
        page.Controls.Add(btnJson);
    }

    // ═════════════════════════════════════════════════════════════════
    // vLLM 탭 빌드
    // ═════════════════════════════════════════════════════════════════
    private void BuildVllmTab(TabPage page)
    {
        int y = 12;
        var desc = CreateLabel("vLLM은 OpenAI 호환 API 서버입니다. API 키는 선택사항입니다.", 9f, FontStyle.Italic);
        desc.ForeColor = TextSecondary;
        desc.Location = new Point(12, y);
        desc.AutoSize = true;
        page.Controls.Add(desc);
        y += 30;

        // Endpoint
        AddFieldPair(page, ref y, "Endpoint URL:", "http://localhost:8000",
            out _vllmEndpoint, out _vllmEncEndpoint, "암호화", AccentBlue, (s, e) =>
            {
                EncryptAndShow(_vllmEndpoint, _vllmEncEndpoint, "vLLM Endpoint");
            });

        // Model
        AddFieldPair(page, ref y, "Model:", "meta-llama/Llama-3.1-8B-Instruct",
            out _vllmModel, out _vllmEncModel, "암호화", AccentBlue, (s, e) =>
            {
                EncryptAndShow(_vllmModel, _vllmEncModel, "vLLM Model");
            });

        // API Key
        AddFieldPair(page, ref y, "API Key (선택):", "",
            out _vllmApiKey, out _vllmEncApiKey, "암호화", AccentBlue, (s, e) =>
            {
                EncryptAndShow(_vllmApiKey, _vllmEncApiKey, "vLLM API Key");
            });

        var btnAll = CreateButton("⚡ 전체 암호화", AccentBlue);
        btnAll.Location = new Point(12, y + 4);
        btnAll.Size = new Size(130, 34);
        btnAll.Click += (s, e) =>
        {
            EncryptAndShow(_vllmEndpoint, _vllmEncEndpoint, "vLLM Endpoint");
            EncryptAndShow(_vllmModel, _vllmEncModel, "vLLM Model");
            if (!string.IsNullOrEmpty(_vllmApiKey.Text.Trim()))
                EncryptAndShow(_vllmApiKey, _vllmEncApiKey, "vLLM API Key");
            AppendLog("[vLLM] 전체 암호화 완료 ✔", AccentGreen);
        };
        page.Controls.Add(btnAll);

        var btnJson = CreateButton("📋  settings.json 복사", AccentBlue);
        btnJson.Location = new Point(150, y + 4);
        btnJson.Size = new Size(200, 34);
        btnJson.Click += (s, e) => GenerateVllmJson();
        page.Controls.Add(btnJson);
    }

    // ═════════════════════════════════════════════════════════════════
    // Gemini 탭 빌드
    // ═════════════════════════════════════════════════════════════════
    private void BuildGeminiTab(TabPage page)
    {
        int y = 12;
        var desc = CreateLabel("Google Gemini API를 사용합니다. API Key가 필수입니다.", 9f, FontStyle.Italic);
        desc.ForeColor = TextSecondary;
        desc.Location = new Point(12, y);
        desc.AutoSize = true;
        page.Controls.Add(desc);
        y += 30;

        // API Key
        AddFieldPair(page, ref y, "API Key (필수):", "",
            out _geminiApiKey, out _geminiEncApiKey, "암호화", AccentOrange, (s, e) =>
            {
                EncryptAndShow(_geminiApiKey, _geminiEncApiKey, "Gemini API Key");
            });

        // Model
        AddFieldPair(page, ref y, "Model:", "gemini-2.0-flash",
            out _geminiModel, out _geminiEncModel, "암호화", AccentOrange, (s, e) =>
            {
                EncryptAndShow(_geminiModel, _geminiEncModel, "Gemini Model");
            });

        var btnAll = CreateButton("⚡ 전체 암호화", AccentOrange);
        btnAll.Location = new Point(12, y + 4);
        btnAll.Size = new Size(130, 34);
        btnAll.Click += (s, e) =>
        {
            EncryptAndShow(_geminiApiKey, _geminiEncApiKey, "Gemini API Key");
            EncryptAndShow(_geminiModel, _geminiEncModel, "Gemini Model");
            AppendLog("[Gemini] 전체 암호화 완료 ✔", AccentGreen);
        };
        page.Controls.Add(btnAll);

        var btnJson = CreateButton("📋  settings.json 복사", AccentOrange);
        btnJson.Location = new Point(150, y + 4);
        btnJson.Size = new Size(200, 34);
        btnJson.Click += (s, e) => GenerateGeminiJson();
        page.Controls.Add(btnJson);
    }

    // ═════════════════════════════════════════════════════════════════
    // 필드 쌍 헬퍼 (라벨 + 입력 + 암호화 버튼 + 결과)
    // ═════════════════════════════════════════════════════════════════
    // ═══════════════════════════════════════════════════════════════════════
    // 복호화 검증 탭
    // ═══════════════════════════════════════════════════════════════════════
    private void BuildToolsTab(TabPage page)
    {
        int y = 12;
        var desc = CreateLabel("암호화된 Base64 값을 붙여넣고 원문을 확인합니다.", 9f, FontStyle.Italic);
        desc.ForeColor = TextSecondary;
        desc.Location = new Point(12, y);
        desc.AutoSize = true;
        page.Controls.Add(desc);
        y += 30;

        var inputLabel = CreateLabel("암호화된 값 (Base64):", 9f, FontStyle.Regular);
        inputLabel.Location = new Point(12, y);
        inputLabel.AutoSize = true;
        page.Controls.Add(inputLabel);
        y += 20;

        _decryptInput = CreateTextBox();
        _decryptInput.Location = new Point(12, y);
        _decryptInput.Size = new Size(440, 28);
        page.Controls.Add(_decryptInput);

        var btnDecrypt = CreateButton("복호화", AccentBlue);
        btnDecrypt.Location = new Point(460, y - 1);
        btnDecrypt.Size = new Size(80, 30);
        btnDecrypt.Click += BtnDecrypt_Click;
        page.Controls.Add(btnDecrypt);

        var btnVerify = CreateButton("왕복 검증", Color.FromArgb(130, 100, 220));
        btnVerify.Location = new Point(546, y - 1);
        btnVerify.Size = new Size(90, 30);
        btnVerify.Click += BtnVerify_Click;
        page.Controls.Add(btnVerify);
        y += 40;

        var resultLabel = CreateLabel("복호화 결과:", 9f, FontStyle.Regular);
        resultLabel.Location = new Point(12, y);
        resultLabel.AutoSize = true;
        page.Controls.Add(resultLabel);
        y += 20;

        _decryptResult = CreateTextBox();
        _decryptResult.Location = new Point(12, y);
        _decryptResult.Size = new Size(624, 28);
        _decryptResult.ReadOnly = true;
        page.Controls.Add(_decryptResult);
    }

    private void AddFieldPair(TabPage page, ref int y,
        string labelText, string placeholder,
        out TextBox input, out TextBox encrypted,
        string buttonText, Color accentColor, EventHandler onClick)
    {
        var lbl = CreateLabel(labelText, 9f, FontStyle.Regular);
        lbl.Location = new Point(12, y);
        lbl.AutoSize = true;
        page.Controls.Add(lbl);
        y += 22;

        input = CreateTextBox();
        input.Location = new Point(12, y);
        input.Size = new Size(310, 28);
        input.PlaceholderText = placeholder;
        if (!string.IsNullOrEmpty(placeholder) && placeholder.StartsWith("http"))
            input.Text = placeholder;
        page.Controls.Add(input);

        var btn = CreateButton(buttonText, accentColor);
        btn.Location = new Point(328, y - 1);
        btn.Size = new Size(70, 30);
        btn.Click += onClick;
        page.Controls.Add(btn);

        encrypted = CreateTextBox();
        encrypted.Location = new Point(404, y);
        encrypted.Size = new Size(238, 28);
        encrypted.ReadOnly = true;
        encrypted.PlaceholderText = "암호화 결과";
        page.Controls.Add(encrypted);

        // 복사 버튼
        var btnCopy = CreateCopyButton(encrypted);
        btnCopy.Location = new Point(646, y);
        btnCopy.Size = new Size(28, 28);
        page.Controls.Add(btnCopy);

        y += 40;
    }

    // ═════════════════════════════════════════════════════════════════
    // 암호화 실행
    // ═════════════════════════════════════════════════════════════════
    private void EncryptAndShow(TextBox input, TextBox output, string fieldName)
    {
        var text = input.Text.Trim();
        if (string.IsNullOrEmpty(text))
        {
            AppendLog($"[{fieldName}] 입력이 비어 있습니다.", AccentRed);
            return;
        }
        var enc = CryptoHelper.Encrypt(text);
        output.Text = enc;
        AppendLog($"[{fieldName}] 암호화 완료 ✔", AccentGreen);
        AppendLog($"  원본: {text}", TextSecondary);
        AppendLog($"  결과: {enc}", TextPrimary);
    }

    // ═════════════════════════════════════════════════════════════════
    // 복호화
    // ═════════════════════════════════════════════════════════════════
    private void BtnDecrypt_Click(object? sender, EventArgs e)
    {
        var b64 = _decryptInput.Text.Trim();
        if (string.IsNullOrEmpty(b64))
        {
            AppendLog("[복호화] 입력이 비어 있습니다.", AccentRed);
            return;
        }
        var (success, result) = CryptoHelper.Decrypt(b64);
        _decryptResult.Text = result;
        if (success)
        {
            _decryptResult.ForeColor = AccentGreen;
            AppendLog($"[복호화] 성공 ✔ → {result}", AccentGreen);
        }
        else
        {
            _decryptResult.ForeColor = AccentRed;
            AppendLog($"[복호화] 실패 ✘ — {result}", AccentRed);
        }
    }

    // ═════════════════════════════════════════════════════════════════
    // 왕복 검증
    // ═════════════════════════════════════════════════════════════════
    private void BtnVerify_Click(object? sender, EventArgs e)
    {
        var b64 = _decryptInput.Text.Trim();
        string testText;
        if (string.IsNullOrEmpty(b64))
        {
            testText = "test-api-key-12345";
            AppendLog("[왕복 검증] 테스트 문자열 사용: " + testText, TextSecondary);
        }
        else
        {
            // 이미 암호화된 값이면 복호화 → 재암호화 → 재복호화
            var (ok, dec) = CryptoHelper.Decrypt(b64);
            if (ok) testText = dec;
            else testText = b64; // 평문으로 간주
        }

        var encrypted = CryptoHelper.Encrypt(testText);
        var (success, decrypted) = CryptoHelper.Decrypt(encrypted);
        var match = success && testText == decrypted;

        _decryptResult.Text = match ? $"✅ 일치 — {decrypted}" : $"❌ 불일치";
        _decryptResult.ForeColor = match ? AccentGreen : AccentRed;

        AppendLog("[왕복 검증]", AccentBlue);
        AppendLog($"  원본:   {testText}", TextSecondary);
        AppendLog($"  암호화: {encrypted}", TextSecondary);
        AppendLog($"  복호화: {decrypted}", TextSecondary);
        AppendLog($"  결과:   {(match ? "✅ 성공" : "❌ 실패")}", match ? AccentGreen : AccentRed);
    }

    // ═════════════════════════════════════════════════════════════════
    // JSON 생성 (서비스별)
    // ═════════════════════════════════════════════════════════════════
    private void GenerateOllamaJson()
    {
        var endpoint = _ollamaEncEndpoint.Text;
        var model = _ollamaEncModel.Text;

        if (string.IsNullOrEmpty(endpoint)) endpoint = CryptoHelper.Encrypt(_ollamaEndpoint.Text);
        if (string.IsNullOrEmpty(model)) model = CryptoHelper.Encrypt(_ollamaModel.Text);

        var json = JsonSerializer.Serialize(new
        {
            llm = new
            {
                service = "ollama",
                encryptedEndpoint = endpoint,
                encryptedModel = model,
                streaming = true,
                maxContextTokens = 4096,
                temperature = 0.7
            }
        }, new JsonSerializerOptions { WriteIndented = true });

        CopyToClipboard(json, "Ollama");
    }

    private void GenerateVllmJson()
    {
        var endpoint = _vllmEncEndpoint.Text;
        var model = _vllmEncModel.Text;
        var apiKey = _vllmEncApiKey.Text;

        if (string.IsNullOrEmpty(endpoint)) endpoint = CryptoHelper.Encrypt(_vllmEndpoint.Text);
        if (string.IsNullOrEmpty(model)) model = CryptoHelper.Encrypt(_vllmModel.Text);
        if (string.IsNullOrEmpty(apiKey) && !string.IsNullOrEmpty(_vllmApiKey.Text))
            apiKey = CryptoHelper.Encrypt(_vllmApiKey.Text);

        var obj = new Dictionary<string, object>
        {
            ["llm"] = new Dictionary<string, object>
            {
                ["service"] = "vllm",
                ["encryptedEndpoint"] = endpoint,
                ["encryptedModel"] = model,
                ["encryptedApiKey"] = apiKey ?? "",
                ["streaming"] = true,
                ["maxContextTokens"] = 4096,
                ["temperature"] = 0.7
            }
        };

        var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions { WriteIndented = true });
        CopyToClipboard(json, "vLLM");
    }

    private void GenerateGeminiJson()
    {
        var apiKey = _geminiEncApiKey.Text;
        var model = _geminiEncModel.Text;

        if (string.IsNullOrEmpty(apiKey))
        {
            if (string.IsNullOrEmpty(_geminiApiKey.Text))
            {
                AppendLog("[Gemini] API Key는 필수입니다!", AccentRed);
                return;
            }
            apiKey = CryptoHelper.Encrypt(_geminiApiKey.Text);
        }
        if (string.IsNullOrEmpty(model)) model = CryptoHelper.Encrypt(_geminiModel.Text);

        var json = JsonSerializer.Serialize(new
        {
            llm = new
            {
                service = "gemini",
                encryptedApiKey = apiKey,
                encryptedModel = model,
                streaming = true,
                maxContextTokens = 8192,
                temperature = 0.7
            }
        }, new JsonSerializerOptions { WriteIndented = true });

        CopyToClipboard(json, "Gemini");
    }

    private void CopyToClipboard(string json, string serviceName)
    {
        Clipboard.SetText(json);
        AppendLog($"[{serviceName}] settings.json 설정값이 클립보드에 복사되었습니다! 📋", AccentGreen);
        AppendLog(json, TextSecondary);
        AppendLog("", TextSecondary);

        // 짧은 알림
        var tip = new ToolTip();
        tip.Show($"{serviceName} 설정이 클립보드에 복사됨!", this, Width / 2 - 100, Height - 60, 2000);
    }

    // ═════════════════════════════════════════════════════════════════
    // 출력 로그
    // ═════════════════════════════════════════════════════════════════
    private void AppendLog(string text, Color color)
    {
        _outputBox.SelectionStart = _outputBox.TextLength;
        _outputBox.SelectionLength = 0;
        _outputBox.SelectionColor = color;
        _outputBox.AppendText(text + Environment.NewLine);
        _outputBox.ScrollToCaret();
    }

    // ═════════════════════════════════════════════════════════════════
    // UI 팩토리 헬퍼
    // ═════════════════════════════════════════════════════════════════
    private static Label CreateLabel(string text, float fontSize, FontStyle style)
    {
        return new Label
        {
            Text = text,
            ForeColor = TextPrimary,
            Font = new Font("Segoe UI", fontSize, style),
            AutoSize = true
        };
    }

    private static TextBox CreateTextBox()
    {
        return new TextBox
        {
            BackColor = BgInput,
            ForeColor = TextPrimary,
            Font = new Font("Segoe UI", 10f),
            BorderStyle = BorderStyle.FixedSingle
        };
    }

    private Button CreateButton(string text, Color bgColor)
    {
        var btn = new Button
        {
            Text = text,
            BackColor = bgColor,
            ForeColor = Color.White,
            FlatStyle = FlatStyle.Flat,
            Font = new Font("Segoe UI", 9f, FontStyle.Bold),
            Cursor = Cursors.Hand
        };
        btn.FlatAppearance.BorderSize = 0;
        btn.FlatAppearance.MouseOverBackColor = ControlPaint.Light(bgColor, 0.15f);
        btn.FlatAppearance.MouseDownBackColor = ControlPaint.Dark(bgColor, 0.1f);
        return btn;
    }

    private Button CreateCopyButton(TextBox target)
    {
        var btn = new Button
        {
            Text = "📋",
            BackColor = BgCard,
            ForeColor = TextPrimary,
            FlatStyle = FlatStyle.Flat,
            Font = new Font("Segoe UI", 9f),
            Cursor = Cursors.Hand
        };
        btn.FlatAppearance.BorderSize = 1;
        btn.FlatAppearance.BorderColor = BorderColor;
        btn.Click += (s, e) =>
        {
            if (!string.IsNullOrEmpty(target.Text))
            {
                Clipboard.SetText(target.Text);
                var tip = new ToolTip();
                tip.Show("복사됨!", btn, 0, -20, 1200);
            }
        };
        return btn;
    }

    private TabPage CreateTabPage(string title, Color accentColor)
    {
        var page = new TabPage(title)
        {
            BackColor = BgPanel,
            ForeColor = TextPrimary,
            Padding = new Padding(4)
        };
        page.Tag = accentColor; // 탭 드로잉에 사용
        return page;
    }

    private void DrawTab(object? sender, DrawItemEventArgs e)
    {
        if (sender is not TabControl tabs) return;
        var page = tabs.TabPages[e.Index];
        var isSelected = e.Index == tabs.SelectedIndex;
        var accent = page.Tag is Color c ? c : AccentBlue;

        // 배경
        var bgColor = isSelected ? BgCard : BgPanel;
        using var bgBrush = new SolidBrush(bgColor);
        e.Graphics.FillRectangle(bgBrush, e.Bounds);

        // 선택된 탭 하단 악센트 라인
        if (isSelected)
        {
            using var lineBrush = new SolidBrush(accent);
            e.Graphics.FillRectangle(lineBrush,
                new Rectangle(e.Bounds.Left, e.Bounds.Bottom - 3, e.Bounds.Width, 3));
        }

        // 텍스트
        var textColor = isSelected ? TextPrimary : TextSecondary;
        using var textBrush = new SolidBrush(textColor);
        var textFont = isSelected
            ? new Font("Segoe UI", 10f, FontStyle.Bold)
            : new Font("Segoe UI", 9.5f, FontStyle.Regular);
        var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
        e.Graphics.DrawString(page.Text, textFont, textBrush, e.Bounds, sf);
        textFont.Dispose();
    }
}
