using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Win32;

namespace DomainJoinTool
{
    public class MainForm : Form
    {
        // ── Cereda/Zelo Colors ────────────────────────────────────────────────
        static readonly Color CTeal  = ColorTranslator.FromHtml("#0D9488");
        static readonly Color CTealD = ColorTranslator.FromHtml("#0F766E");
        static readonly Color CGreen = ColorTranslator.FromHtml("#059669");
        static readonly Color CRed   = ColorTranslator.FromHtml("#DC2626");
        static readonly Color CAmber = ColorTranslator.FromHtml("#D97706");
        static readonly Color CGray  = ColorTranslator.FromHtml("#6B7280");
        static readonly Color CBG    = ColorTranslator.FromHtml("#F8FAFC");
        static readonly Color CBorder= ColorTranslator.FromHtml("#E2E8F0");
        static readonly Color CText  = ColorTranslator.FromHtml("#0F172A");
        static readonly Color CText2 = ColorTranslator.FromHtml("#64748B");

        // ── State ─────────────────────────────────────────────────────────────
        bool _entra, _domain; string _dn = ""; int _step;
        Timer _animTimer; float _phase, _spin;

        // ── Controls ──────────────────────────────────────────────────────────
        StatusBadge _badge;
        Panel _body1, _body2;
        ModernInput _txUser, _txPass;
        RoundButton _btnJoin, _btnLeave, _btnMig;
        Label _lnkBack, _lnkTab1, _lnkTab2;
        ComboBox _cbSrc, _cbDst;
        ProgressBar _pb; Label _lbPb;
        RichTextBox _log;
        Label _lblStat;
        Label _lblMigStatus;
        ProgressBar _pbMig;
        Label _lblMigCount;
        RichTextBox _logMig;

        const string DOM = "winkel.local";
        const string LOG = @"C:\ProgramData\DomainJoinTool\join.log";
        const string FLG = @"C:\ProgramData\DomainJoinTool\pending-migration.txt";
        const string EXE = @"C:\ProgramData\DomainJoinTool\DomainJoinTool.exe";

        public MainForm()
        {
            Text = "Cereda Systems  ·  Domain Join Tool";
            ClientSize = new Size(620, 680);
            FormBorderStyle = FormBorderStyle.FixedSingle;
            MaximizeBox = false; StartPosition = FormStartPosition.CenterScreen;
            BackColor = CBG; Font = new Font("Segoe UI", 9f); Icon = MakeIcon();
            Build();
            _animTimer = new Timer { Interval = 16 };
            _animTimer.Tick += (s, e) => { _phase = (_phase + 0.025f) % 1f; _spin = (_spin + 9f) % 360f; _badge?.Tick(_phase, _spin); };
            _animTimer.Start();
            DetectStatus();
            LoadProfiles();
        }

        void Build()
        {
            // ── Header ────────────────────────────────────────────────────────
            var hdr = new Panel { Dock = DockStyle.Top, Height = 64, BackColor = CTeal };
            hdr.Paint += (s, e) =>
            {
                var g = e.Graphics;
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
                // Subtle darker stripe at bottom
                using (var br = new SolidBrush(Color.FromArgb(30, 0, 0, 0)))
                    g.FillRectangle(br, 0, hdr.Height - 3, hdr.Width, 3);
                // Logo circle
                using (var br = new SolidBrush(Color.FromArgb(40, 255, 255, 255)))
                    g.FillEllipse(br, 14, 10, 36, 36);
                using (var f = new Font("Segoe UI", 11f, FontStyle.Bold))
                using (var br = new SolidBrush(Color.White))
                { var sf = new System.Drawing.StringFormat { Alignment = System.Drawing.StringAlignment.Center, LineAlignment = System.Drawing.StringAlignment.Center }; g.DrawString("IT", f, br, new RectangleF(14, 10, 36, 36), sf); }
                // Text
                using (var br = new SolidBrush(Color.FromArgb(200, 255, 255, 255)))
                    g.DrawString("CEREDA SYSTEMS", new Font("Segoe UI", 7.5f, FontStyle.Bold), br, 60, 12);
                g.DrawString("Domain Join Tool", new Font("Segoe UI", 13f, FontStyle.Bold), Brushes.White, 58, 28);
                // Version badge
                using (var br = new SolidBrush(Color.FromArgb(40, 255, 255, 255)))
                    g.FillRectangle(br, hdr.Width - 68, 20, 56, 20);
                using (var br = new SolidBrush(Color.FromArgb(200, 255, 255, 255)))
                    g.DrawString("v2.5.0", new Font("Segoe UI", 8f), br, new RectangleF(hdr.Width - 68, 20, 56, 20),
                        new System.Drawing.StringFormat { Alignment = System.Drawing.StringAlignment.Center, LineAlignment = System.Drawing.StringAlignment.Center });
            };
            Controls.Add(hdr);

            // ── Tab bar ───────────────────────────────────────────────────────
            var tabBar = new Panel { Dock = DockStyle.Top, Height = 38, BackColor = Color.White };
            tabBar.Paint += (s, e) => {
                e.Graphics.DrawLine(new Pen(CBorder), 0, 37, 600, 37);
                // Active indicator
                if (_step == 0) e.Graphics.FillRectangle(new SolidBrush(CTeal), 16, 35, 120, 3);
                else            e.Graphics.FillRectangle(new SolidBrush(CTeal), 148, 35, 140, 3);
            };
            _lnkTab1 = TabLabel("1  ·  Domain Join", new Point(16, 8), true);
            _lnkTab2 = TabLabel("2  ·  Profil Migration", new Point(148, 8), false);
            _lnkTab1.Click += (s, e) => GoTo(0, tabBar);
            _lnkTab2.Click += (s, e) => GoTo(1, tabBar);
            tabBar.Controls.Add(_lnkTab1); tabBar.Controls.Add(_lnkTab2);
            Controls.Add(tabBar);

            // ── Bodies (explicit position to avoid Dock=Fill overlap bug) ────
            // hdr=64 + tabBar=38 = 102px
            _body1 = new Panel { Location = new Point(0, 102), Size = new Size(620, 578), BackColor = CBG };
            _body2 = new Panel { Location = new Point(0, 102), Size = new Size(620, 578), BackColor = CBG, Visible = false };
            BuildBody1(); BuildBody2();
            Controls.Add(_body1); Controls.Add(_body2);
        }

        Label TabLabel(string t, Point loc, bool active)
        {
            var l = new Label { Text = t, Font = new Font("Segoe UI", 9f, active ? FontStyle.Bold : FontStyle.Regular), ForeColor = active ? CTeal : CText2, Location = loc, AutoSize = true, Cursor = Cursors.Hand };
            l.MouseEnter += (s, e) => l.ForeColor = CTeal;
            l.MouseLeave += (s, e) => l.ForeColor = (_step == (l == _lnkTab1 ? 0 : 1)) ? CTeal : CText2;
            return l;
        }

        void GoTo(int step, Panel tabBar = null)
        {
            _step = step; _body1.Visible = step == 0; _body2.Visible = step == 1;
            _lnkTab1.Font = new Font("Segoe UI", 9f, step == 0 ? FontStyle.Bold : FontStyle.Regular);
            _lnkTab2.Font = new Font("Segoe UI", 9f, step == 1 ? FontStyle.Bold : FontStyle.Regular);
            _lnkTab1.ForeColor = step == 0 ? CTeal : CText2;
            _lnkTab2.ForeColor = step == 1 ? CTeal : CText2;
            (tabBar ?? _body1.Parent?.Parent as Panel)?.Invalidate();
            // Find and invalidate the tabBar
            foreach (Control c in Controls) if (c is Panel p && p.Height == 38) { p.Invalidate(); break; }
        }

        // ── Body 1: Domain Join ───────────────────────────────────────────────
        void BuildBody1()
        {
            int m = 16, y = 14, w = 588;

            // ── Status Card ───────────────────────────────────────────────────
            var statCard = MkCard(m, y, w, 86); y += 98;

            _lblStat = new Label { Text = "Status", Font = new Font("Segoe UI", 9f, FontStyle.Bold), ForeColor = CTealD, Location = new Point(20, 10), AutoSize = true };
            statCard.Controls.Add(_lblStat);
            statCard.Controls.Add(new Panel { Location = new Point(20, 30), Size = new Size(w - 26, 1), BackColor = CBorder });

            _badge = new StatusBadge { Location = new Point(20, 40) };
            statCard.Controls.Add(_badge);

            // Right: Entra → AD
            statCard.Controls.Add(new Label { Text = "Entra ID", Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = CText2, Location = new Point(280, 38), AutoSize = true });
            statCard.Controls.Add(new Label { Text = "→", Font = new Font("Segoe UI", 14f), ForeColor = Color.FromArgb(180, 180, 200), Location = new Point(358, 32), AutoSize = true });
            statCard.Controls.Add(new Label { Text = DOM, Font = new Font("Segoe UI", 8.5f, FontStyle.Bold), ForeColor = CGreen, Location = new Point(382, 38), AutoSize = true });
            statCard.Controls.Add(new Label { Text = Environment.MachineName, Font = new Font("Cascadia Mono", 7.5f), ForeColor = CText2, Location = new Point(280, 57), AutoSize = true });
            _body1.Controls.Add(statCard);

            // ── Credentials Card ──────────────────────────────────────────────
            var credCard = MkCard(m, y, w, 168); y += 180;

            credCard.Controls.Add(new Label { Text = "Domain-Zugangsdaten", Font = new Font("Segoe UI", 10f, FontStyle.Bold), ForeColor = CTealD, Location = new Point(20, 12), AutoSize = true });
            credCard.Controls.Add(new Label { Text = "Ziel: " + DOM, Font = new Font("Cascadia Mono", 8f, FontStyle.Bold), ForeColor = CGreen, Location = new Point(220, 15), AutoSize = true });
            credCard.Controls.Add(new Panel { Location = new Point(20, 36), Size = new Size(w - 26, 1), BackColor = CBorder });
            _txUser = Inp(new Point(20, 44), new Size(w - 40, 52), "Benutzername"); _txUser.Val = "Administrator";
            _txPass = Inp(new Point(20, 104), new Size(w - 40, 52), "Passwort", true);
            credCard.Controls.Add(_txUser); credCard.Controls.Add(_txPass);
            _body1.Controls.Add(credCard);

            // ── Action Buttons ────────────────────────────────────────────────
            _btnJoin  = new RoundButton("▶  Entra leaven + Domain joinen", CTeal, 10) { Location = new Point(m, y), Size = new Size(420, 44) };
            _btnLeave = new RoundButton("■  Nur Entra verlassen",           CRed,  10) { Location = new Point(m + 428, y), Size = new Size(160, 44) };
            _btnJoin.Click  += DoJoin; _btnLeave.Click += DoLeave;
            _body1.Controls.Add(_btnJoin); _body1.Controls.Add(_btnLeave); y += 52;

            // ── Progress ─────────────────────────────────────────────────────
            _pb   = new ProgressBar { Location = new Point(m, y), Size = new Size(w, 4), Style = ProgressBarStyle.Marquee, MarqueeAnimationSpeed = 25, Visible = false }; y += 8;
            _lbPb = Lbl("Bitte warten…", new Point(m, y)); _lbPb.Visible = false; y += 22;
            _body1.Controls.Add(_pb); _body1.Controls.Add(_lbPb);

            // ── Log ───────────────────────────────────────────────────────────
            _body1.Controls.Add(Lbl("Log  ·  " + LOG, new Point(m, y), new Font("Cascadia Mono", 7.5f), CText2)); y += 16;
            _log = new RichTextBox { Location = new Point(m, y), Size = new Size(w, 100), BackColor = Color.FromArgb(13, 17, 23), ForeColor = Color.FromArgb(100, 210, 130), Font = new Font("Cascadia Mono", 8f), ReadOnly = true, BorderStyle = BorderStyle.None };
            _body1.Controls.Add(_log);
        }

        // ── Body 2: Migration ─────────────────────────────────────────────────
        void BuildBody2()
        {
            int m = 16, y = 14, w = 588;

            var infoCard = MkCard(m, y, w, 140); y += 152;
            infoCard.Controls.Add(new Label { Text = "Was wird migriert", Font = new Font("Segoe UI", 10f, FontStyle.Bold), ForeColor = CTealD, Location = new Point(20, 12), AutoSize = true });
            infoCard.Controls.Add(new Panel { Location = new Point(20, 36), Size = new Size(w - 26, 1), BackColor = CBorder });
            int iy = 46;
            foreach (var (t, ok) in new[] {
                ("Dokumente, Desktop, Downloads, Bilder, Videos, Musik", true),
                ("AppData\\Roaming  —  Outlook, Edge, Chrome, App-Einstellungen", true),
                ("Hintergrundbild, Taskbar-Pins, Startmenü-Layout", true),
                ("Temp-Cache, NTUSER.DAT  —  nicht übertragen", false),
            }) { infoCard.Controls.Add(Lbl((ok ? "✓  " : "✗  ") + t, new Point(20, iy), null, ok ? CGreen : CAmber)); iy += 24; }
            _body2.Controls.Add(infoCard);

            var selCard = MkCard(m, y, w, 108); y += 120;
            selCard.Controls.Add(new Label { Text = "Profile auswählen", Font = new Font("Segoe UI", 10f, FontStyle.Bold), ForeColor = CTealD, Location = new Point(20, 12), AutoSize = true });
            selCard.Controls.Add(new Panel { Location = new Point(20, 36), Size = new Size(w - 26, 1), BackColor = CBorder });
            selCard.Controls.Add(Lbl("Von (altes Entra-Profil):", new Point(20, 46)));
            selCard.Controls.Add(Lbl("Nach (neues Domain-Profil):", new Point(20, 76)));
            _cbSrc = Cmb(new Point(210, 43), new Size(w - 230, 24));
            _cbDst = Cmb(new Point(210, 73), new Size(w - 230, 24));
            selCard.Controls.Add(_cbSrc); selCard.Controls.Add(_cbDst);
            _body2.Controls.Add(selCard);

            _btnMig = new RoundButton("▶  Profil jetzt migrieren", CGreen, 10) { Location = new Point(m, y), Size = new Size(440, 44) }; y += 52;
            _btnMig.Click += DoMig;
            _lnkBack = new Label { Text = "← Zurück zu Domain Join", Font = new Font("Segoe UI", 9f), ForeColor = CText2, Location = new Point(m + 448, y - 40), AutoSize = true, Cursor = Cursors.Hand };
            _lnkBack.Click += (s, e) => GoTo(0);
            _lnkBack.MouseEnter += (s, e) => _lnkBack.ForeColor = CTeal;
            _lnkBack.MouseLeave += (s, e) => _lnkBack.ForeColor = CText2;
            _body2.Controls.Add(_btnMig); _body2.Controls.Add(_lnkBack);

            // ── Status + Progress + Log (Tab 2) ──────────────────────────────
            _lblMigStatus = new Label { Text = "", Font = new Font("Segoe UI", 9f, FontStyle.Bold), ForeColor = CTealD, Location = new Point(m, y), AutoSize = true };
            _lblMigCount  = new Label { Text = "", Font = new Font("Cascadia Mono", 8f), ForeColor = CText2, Location = new Point(m + 300, y), AutoSize = true };
            y += 22;
            _pbMig = new ProgressBar { Location = new Point(m, y), Size = new Size(w, 6), Style = ProgressBarStyle.Marquee, MarqueeAnimationSpeed = 20, Visible = false }; y += 14;
            _logMig = new RichTextBox { Location = new Point(m, y), Size = new Size(w, 106), BackColor = Color.FromArgb(13, 17, 23), ForeColor = Color.FromArgb(100, 210, 130), Font = new Font("Cascadia Mono", 8f), ReadOnly = true, BorderStyle = BorderStyle.None, Visible = false };
            _body2.Controls.Add(_lblMigStatus); _body2.Controls.Add(_lblMigCount);
            _body2.Controls.Add(_pbMig); _body2.Controls.Add(_logMig);
        }

        // ── State ─────────────────────────────────────────────────────────────
        void DetectStatus()
        {
            Task.Run(new Action(() => {
                try { var r = Run("dsregcmd", "/status", 10000); _entra = r.Contains("AzureAdJoined : YES"); _domain = r.Contains("DomainJoined : YES"); foreach (var ln in r.Split('\n')) if (ln.Trim().StartsWith("DomainName :")) { _dn = ln.Split(':')[1].Trim(); break; } } catch { }
                Invoke(new Action(() => { RefreshStat(); CheckAutoMig(); }));
            }));
        }

        void RefreshStat()
        {
            if (_domain) { _badge.Mode = StatusBadge.BMode.Joined; _lblStat.Text = "Domain joined: " + _dn; _lblStat.ForeColor = CGreen; _btnJoin.Text = "↺  Domain wechseln"; _btnLeave.Text = "■  Verlassen"; }
            else if (_entra) { _badge.Mode = StatusBadge.BMode.Entra; _lblStat.Text = "Entra ID joined  —  bereit für Domain-Join"; _lblStat.ForeColor = CTealD; }
            else { _badge.Mode = StatusBadge.BMode.None; _lblStat.Text = "Workgroup  —  kein Domain-Join"; _lblStat.ForeColor = CAmber; _btnLeave.Enabled = false; }
        }

        void CheckAutoMig()
        {
            if (!File.Exists(FLG) || !_domain) return;
            try {
                var old = File.ReadAllText(FLG).Trim(); LoadProfiles();
                for (int i = 0; i < _cbSrc.Items.Count; i++) if (_cbSrc.Items[i].ToString().Equals(old, StringComparison.OrdinalIgnoreCase)) { _cbSrc.SelectedIndex = i; break; }
                var cur = Environment.UserName;
                for (int i = 0; i < _cbDst.Items.Count; i++) if (_cbDst.Items[i].ToString().Equals(cur, StringComparison.OrdinalIgnoreCase)) { _cbDst.SelectedIndex = i; break; }
                GoTo(1);
                if (MessageBox.Show("Domain-Join erfolgreich!\n\nProfil migrieren?\n  Von: C:\\Users\\" + old + "\n  Nach: C:\\Users\\" + cur, "Profil Migration", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                    DoMig(null, EventArgs.Empty);
                else File.Delete(FLG);
            } catch { }
        }

        void LoadProfiles()
        {
            if (_cbSrc == null) return;
            var list = new List<string>();
            if (Directory.Exists(@"C:\Users")) foreach (var d in Directory.GetDirectories(@"C:\Users")) { var n = Path.GetFileName(d); if (n != "Public" && n != "Default" && n != "Default User" && n != "All Users") list.Add(n); }
            _cbSrc.Items.Clear(); _cbDst.Items.Clear();
            foreach (var p in list) { _cbSrc.Items.Add(p); _cbDst.Items.Add(p); }
            if (_cbSrc.Items.Count > 0) _cbSrc.SelectedIndex = 0;
            if (_cbDst.Items.Count > 1) _cbDst.SelectedIndex = 1;
        }

        // ── Actions ───────────────────────────────────────────────────────────
        async void DoJoin(object s, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(_txUser.Val) || string.IsNullOrWhiteSpace(_txPass.Val)) { MessageBox.Show("Bitte Benutzername und Passwort eingeben.", "Eingabe fehlt", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; }
            if (MessageBox.Show("Computer wird der Domain '" + DOM + "' beigetreten.\n\nFortfahren?", "Bestätigung", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
            Busy(true, "Domain-Wechsel läuft…"); _badge.Mode = StatusBadge.BMode.Working;
            var user = _txUser.Val.Trim(); var pass = _txPass.Val;
            await Task.Run(new Action(async () => {
                if (_entra) { Prog("Entra ID verlassen…"); Log(Run("dsregcmd", "/leave", 30000)); await Task.Delay(2000); }
                Prog("Domain joinen…");
                if (!user.Contains("\\") && !user.Contains("@")) user = DOM + "\\" + user;
                var res = PS("$pw=ConvertTo-SecureString '" + Esc(pass) + "' -AsPlainText -Force; $cr=New-Object System.Management.Automation.PSCredential('" + Esc(user) + "',$pw); Add-Computer -DomainName '" + DOM + "' -Credential $cr -Force 2>&1");
                Log(res);
                var ok = !res.ToLower().Contains("fehler") && !res.ToLower().Contains("error") && !res.ToLower().Contains("failed") && !res.ToLower().Contains("denied");
                if (ok) SetupAutoMig();
                Invoke(new Action(() => {
                    Busy(false, "");
                    if (ok) { if (MessageBox.Show("Erfolgreich!\n\nJetzt neu starten?", "✓ Fertig", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes) Run("shutdown", "/r /t 5 /c \"Domain Join\""); }
                    else MessageBox.Show("Fehlgeschlagen — Log prüfen.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    DetectStatus();
                }));
            }));
        }

        async void DoLeave(object s, EventArgs e)
        {
            if (MessageBox.Show("Computer verlässt " + (_domain ? "Domain '" + _dn + "'" : "Entra ID") + ".\n\nFortfahren?", "Bestätigung", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
            Busy(true, "Verlasse…"); _badge.Mode = StatusBadge.BMode.Working;
            await Task.Run(new Action(() => { Log(Run("dsregcmd", "/leave", 30000)); Invoke(new Action(() => { Busy(false, ""); MessageBox.Show("Fertig. Bitte neu starten.", "Erledigt", MessageBoxButtons.OK, MessageBoxIcon.Information); DetectStatus(); })); }));
        }

        void SetupAutoMig()
        {
            try { Directory.CreateDirectory(Path.GetDirectoryName(FLG)); File.WriteAllText(FLG, Environment.UserName); File.Copy(System.Reflection.Assembly.GetExecutingAssembly().Location, EXE, true); using (var k = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce", true)) k.SetValue("DomainJoinMigration", "\"" + EXE + "\""); Log("[AUTO] Migration startet nach nächstem Login automatisch"); } catch (Exception ex) { Log("[WARN] " + ex.Message); }
        }

        async void DoMig(object s, EventArgs e)
        {
            if (_cbSrc.SelectedItem == null || _cbDst.SelectedItem == null)
            {
                MessageBox.Show("Bitte Quell- und Zielprofil auswählen.", "Profil fehlt", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            var src = _cbSrc.SelectedItem.ToString();
            var dst = _cbDst.SelectedItem.ToString();
            if (src == dst) { MessageBox.Show("Quelle und Ziel sind identisch.", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; }
            var srcPath = @"C:\Users\" + src;
            var dstPath = @"C:\Users\" + dst;
            if (!Directory.Exists(srcPath)) { MessageBox.Show("Quellprofil nicht gefunden:\n" + srcPath, "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
            if (MessageBox.Show("Profil kopieren?\n\nVon:  " + srcPath + "\nNach: " + dstPath + "\n\nDas kann mehrere Minuten dauern.", "Bestätigung", MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;

            _btnMig.Enabled = false;
            _logMig.Visible = true;
            _logMig.Clear();
            _pbMig.Visible = true;
            _lblMigCount.Text = "";
            MigLog("[START] " + src + "  →  " + dst);
            MigStatus("⏳  Migration läuft…");
            Log("[START] Profil-Migration: " + src + " → " + dst);

            await Task.Run(new Action(() =>
            {
                try
                {
                    if (!Directory.Exists(dstPath))
                    {
                        Directory.CreateDirectory(dstPath);
                        MigLog("[INFO] Zielordner angelegt: " + dstPath);
                    }

                    var args = "\"" + srcPath + "\" \"" + dstPath + "\""
                        + " /E /XJ /XC /XN /XO"
                        + " /XA:O"
                        + " /XD Temp INetCache WebCache \"AppData\\Local\\Temp\" OneDrive \"Cereda Systems GmbH\" \"OneDrive - Cereda Systems GmbH\""
                        + " /XF NTUSER.DAT ntuser.dat ntuser.ini \"*.regtrans-ms\" \"*.blf\""
                        + " /R:0 /W:0 /NP";

                    MigLog("[CMD] robocopy " + args);
                    var psi = new System.Diagnostics.ProcessStartInfo(
                        @"C:\Windows\System32\robocopy.exe", args)
                    {
                        RedirectStandardOutput = true,
                        RedirectStandardError  = true,
                        UseShellExecute        = false,
                        CreateNoWindow         = true
                    };
                    int exitCode = -1;
                    int copiedFiles = 0, skippedFiles = 0;
                    using (var proc = System.Diagnostics.Process.Start(psi))
                    {
                        string line;
                        while ((line = proc.StandardOutput.ReadLine()) != null)
                        {
                            MigLog(line);
                            // Count copied files ("Neue Datei" or "New File")
                            if (line.Contains("Neue Datei") || line.Contains("New File"))
                            {
                                copiedFiles++;
                                MigCount("Kopiert: " + copiedFiles + " Dateien" + (skippedFiles > 0 ? "  •  Übersprungen: " + skippedFiles : ""));
                            }
                            else if (line.Contains("FEHLER") || line.Contains("ERROR"))
                            {
                                skippedFiles++;
                                MigCount("Kopiert: " + copiedFiles + " Dateien  •  Übersprungen: " + skippedFiles);
                            }
                        }
                        proc.WaitForExit(1800000);
                        exitCode = proc.ExitCode;
                    }
                    Invoke(new Action(() => _pbMig.Visible = false));
                    // robocopy: 0-7 = OK (0=nichts zu tun, 1=kopiert, 2=extra, etc.), 8+ = Fehler
                    if (exitCode >= 8)
                    {
                        MigLog("[FEHLER] ExitCode=" + exitCode);
                        MigStatus("✗  Fehler (ExitCode " + exitCode + ")");
                    }
                    else
                    {
                        MigLog("[OK] Abgeschlossen. ExitCode=" + exitCode);
                        MigStatus("✓  Migration abgeschlossen — " + copiedFiles + " Dateien kopiert");
                    }

                    try { if (File.Exists(FLG)) File.Delete(FLG); } catch { }

                    Invoke(new Action(() =>
                    {
                        _btnMig.Enabled = true;
                        MessageBox.Show("Migration abgeschlossen!\n\nDateien sind in:\n" + dstPath,
                            "✓ Fertig", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }));
                }
                catch (Exception ex)
                {
                    MigLog("[EXCEPTION] " + ex.Message);
                    MigStatus("✗  Fehler aufgetreten");
                    Log("[EXCEPTION] Migration: " + ex.Message);
                    Invoke(new Action(() =>
                    {
                        _btnMig.Enabled = true;
                        MessageBox.Show("Fehler bei Migration:\n\n" + ex.Message, "Fehler",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }));
                }
            }));
        }

        // ── Helpers ───────────────────────────────────────────────────────────
        void Busy(bool b, string m) { if (InvokeRequired) { Invoke(new Action(() => Busy(b, m))); return; } _btnJoin.Enabled = _btnLeave.Enabled = !b; _pb.Visible = _lbPb.Visible = b; if (!string.IsNullOrEmpty(m)) _lbPb.Text = m; }
        void Prog(string m) { if (InvokeRequired) { Invoke(new Action(() => Prog(m))); return; } _lbPb.Text = m; Log(m); }
        void Log(string t) { if (InvokeRequired) { Invoke(new Action(() => Log(t))); return; } if (string.IsNullOrWhiteSpace(t)) return; var ln = "[" + DateTime.Now.ToString("HH:mm:ss") + "] " + t.Trim(); _log?.AppendText(ln + "\n"); _log?.ScrollToCaret(); try { Directory.CreateDirectory(Path.GetDirectoryName(LOG)); File.AppendAllText(LOG, DateTime.Now.ToString("yyyy-MM-dd") + " " + ln + Environment.NewLine); } catch { } }
        void MigLog(string t) { if (InvokeRequired) { Invoke(new Action(() => MigLog(t))); return; } if (string.IsNullOrWhiteSpace(t)) return; _logMig?.AppendText(t.TrimEnd() + "\n"); _logMig?.ScrollToCaret(); }
        void MigStatus(string t) { if (InvokeRequired) { Invoke(new Action(() => MigStatus(t))); return; } if (_lblMigStatus != null) { _lblMigStatus.Text = t; _lblMigStatus.ForeColor = t.StartsWith("✓") ? CGreen : t.StartsWith("✗") ? CRed : CTealD; } }
        void MigCount(string t) { if (InvokeRequired) { Invoke(new Action(() => MigCount(t))); return; } if (_lblMigCount != null) _lblMigCount.Text = t; }

        // Same pattern as ZeloServerVerwaltung
        Panel MkCard(int x, int y, int w, int h)
        {
            var p = new Panel { Location = new Point(x, y), Size = new Size(w, h), BackColor = Color.White };
            var accent = new Panel { Location = Point.Empty, Size = new Size(5, h), BackColor = CTeal };
            p.Controls.Add(accent);
            p.Paint += (s, e) =>
            {
                var g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias;
                // Border
                using (var path = RR(1, 1, w - 2, h - 2, 10))
                using (var pen = new Pen(Color.FromArgb(215, 225, 235), 1f)) g.DrawPath(pen, path);
                // Subtle bottom shadow line
                using (var pen = new Pen(Color.FromArgb(50, 0, 100, 150), 1.5f))
                    g.DrawLine(pen, 10, h - 1, w - 4, h - 1);
            };
            using (var path = RR(0, 0, w, h, 10))
                p.Region = new Region(path);
            return p;
        }

        Label Lbl(string t, Point loc, Font f = null, Color? c = null) => new Label { Text = t, Font = f ?? new Font("Segoe UI", 9f), ForeColor = c ?? CText2, Location = loc, AutoSize = true };
        ModernInput Inp(Point loc, Size sz, string placeholder = "", bool pw = false)
        {
            return new ModernInput(placeholder, pw) { Location = loc, Size = sz };
        }
        ComboBox Cmb(Point loc, Size sz) => new ComboBox { Location = loc, Size = sz, DropDownStyle = ComboBoxStyle.DropDownList, FlatStyle = FlatStyle.Flat, Font = new Font("Segoe UI", 9f) };

        static GraphicsPath RR(int x, int y, int w, int h, int r) { var p = new GraphicsPath(); p.AddArc(x, y, r * 2, r * 2, 180, 90); p.AddArc(x + w - r * 2, y, r * 2, r * 2, 270, 90); p.AddArc(x + w - r * 2, y + h - r * 2, r * 2, r * 2, 0, 90); p.AddArc(x, y + h - r * 2, r * 2, r * 2, 90, 90); p.CloseFigure(); return p; }
        static Icon MakeIcon()
        {
            var bmp = new Bitmap(32, 32);
            using (var g = Graphics.FromImage(bmp))
            {
                g.SmoothingMode = SmoothingMode.AntiAlias;
                g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;
                // Teal rounded square
                using (var path = RR(0, 0, 32, 32, 6))
                using (var br = new SolidBrush(ColorTranslator.FromHtml("#0D9488")))
                    g.FillPath(br, path);
                // White "C" letter
                var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center };
                g.DrawString("C", new Font("Segoe UI", 16f, FontStyle.Bold), Brushes.White, new RectangleF(0, 0, 32, 32), sf);
            }
            IntPtr hIcon = bmp.GetHicon();
            return Icon.FromHandle(hIcon);
        }

        string Run(string exe, string args, int ms = 60000) { var psi = new ProcessStartInfo(exe, args) { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, CreateNoWindow = true }; using (var p = Process.Start(psi)) { var o = p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd(); p.WaitForExit(ms); return o; } }
        string PS(string sc) => Run("powershell.exe", "-NoProfile -NonInteractive -ExecutionPolicy Bypass -Command \"" + sc.Replace("\"", "\\\"") + "\"", 120000);
        static string Esc(string s) => s.Replace("'", "''");

        protected override void OnFormClosed(FormClosedEventArgs e) { _animTimer?.Stop(); _animTimer?.Dispose(); base.OnFormClosed(e); }

        // ── ModernInput — Floating-Label + Fokus-Effekt + Validierung ─────────
        class ModernInput : Panel
        {
            readonly Label   _lbl;
            readonly TextBox _txt;
            readonly Label   _icon;
            bool _focused, _ready;
            static readonly Color Teal   = ColorTranslator.FromHtml("#0D9488");
            static readonly Color Gray   = ColorTranslator.FromHtml("#94A3B8");
            static readonly Color Border = ColorTranslator.FromHtml("#E2E8F0");
            static readonly Color Green  = ColorTranslator.FromHtml("#059669");
            static readonly Color Red    = ColorTranslator.FromHtml("#DC2626");

            public string Val { get => _txt.Text; set { _txt.Text = value; Update_(); } }

            public ModernInput(string placeholder, bool pw = false)
            {
                DoubleBuffered = true;
                SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint |
                         ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true);
                BackColor = Color.Transparent; Height = 52;

                _lbl = new Label {
                    Text = placeholder,
                    Font = new Font("Segoe UI", 9.5f),
                    ForeColor = Gray,
                    Location = new Point(13, 15),
                    AutoSize = true
                };

                _txt = new TextBox {
                    BorderStyle = BorderStyle.None,
                    Location    = new Point(13, 28),
                    Font        = new Font("Segoe UI", 10.5f),
                    BackColor   = Color.White
                };
                if (pw) _txt.PasswordChar = '●';

                // Validation icon
                _icon = new Label {
                    Font = new Font("Segoe UI", 12f),
                    Text = "",
                    AutoSize = true,
                    ForeColor = Gray
                };

                _txt.GotFocus    += (s, e) => { _focused = true;  Update_(); Invalidate(); };
                _txt.LostFocus   += (s, e) => { _focused = false; Update_(); Invalidate(); };
                _txt.TextChanged += (s, e) => { Update_(); Invalidate(); };

                Controls.Add(_lbl);
                Controls.Add(_txt);
                Controls.Add(_icon);
                _ready = true;
            }

            void Update_()
            {
                bool fl = _focused || !string.IsNullOrEmpty(_txt.Text);
                _lbl.Font      = new Font("Segoe UI", fl ? 7.5f : 9.5f);
                _lbl.Location  = new Point(13, fl ? 6 : 15);
                _lbl.ForeColor = _focused ? Teal : Gray;

                bool filled = !string.IsNullOrWhiteSpace(_txt.Text);
                _icon.Text      = filled ? "✓" : "";
                _icon.ForeColor = filled ? Green : Gray;
                if (_icon.Width > 0)
                    _icon.Location = new Point(Width - _icon.Width - 12, (Height - _icon.Height) / 2);
            }

            protected override void OnResize(EventArgs e)
            {
                base.OnResize(e);
                if (!_ready || _txt == null) return;
                _txt.Width = Width - 32;
                Update_();
            }

            protected override void OnPaint(PaintEventArgs e)
            {
                var g = e.Graphics;
                g.SmoothingMode = SmoothingMode.AntiAlias;

                // White background
                using (var br = new SolidBrush(Color.White))
                    g.FillRectangle(br, 0, 0, Width, Height);

                // Border
                var bc = _focused ? Teal : Border;
                using (var pen = new Pen(bc, _focused ? 2f : 1f))
                    g.DrawRectangle(pen, 0, 0, Width - 1, Height - 1);

                // Bottom accent line on focus
                if (_focused)
                    using (var pen = new Pen(Teal, 2.5f))
                        g.DrawLine(pen, 2, Height - 1, Width - 3, Height - 1);
            }
        }

        // ── RoundButton (same as ZeloServerVerwaltung) ────────────────────────
        class RoundButton : Control
        {
            bool _hov, _press; readonly Color _base, _hov2, _press2; readonly int _r;
            public RoundButton(string text, Color baseColor, int radius = 8)
            {
                _base = baseColor; _hov2 = ControlPaint.Dark(baseColor, 0.10f); _press2 = ControlPaint.Dark(baseColor, 0.20f); _r = radius;
                Text = text; Font = new Font("Segoe UI", 9f, FontStyle.Bold); Cursor = Cursors.Hand;
                SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
            }
            protected override void OnPaint(PaintEventArgs e)
            {
                var g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias;
                g.Clear(Parent?.BackColor ?? Color.White);
                var fill = _press ? _press2 : (_hov && Enabled) ? _hov2 : _base;
                using (var path = RR(0, 0, Width, Height, _r)) using (var br = new SolidBrush(fill)) g.FillPath(br, path);
                if (!Enabled) using (var path = RR(0, 0, Width, Height, _r)) using (var br = new SolidBrush(Color.FromArgb(110, 255, 255, 255))) g.FillPath(br, path);
                TextRenderer.DrawText(e.Graphics, Text, Font, new Rectangle(0, 0, Width, Height), Color.White, TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);
            }
            protected override void OnMouseEnter(EventArgs e) { _hov = true;  Invalidate(); base.OnMouseEnter(e); }
            protected override void OnMouseLeave(EventArgs e) { _hov = false; _press = false; Invalidate(); base.OnMouseLeave(e); }
            protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { _press = true; Invalidate(); } base.OnMouseDown(e); }
            protected override void OnMouseUp(MouseEventArgs e) { _press = false; Invalidate(); base.OnMouseUp(e); }
            protected override void OnEnabledChanged(EventArgs e) { Cursor = Enabled ? Cursors.Hand : Cursors.Default; Invalidate(); base.OnEnabledChanged(e); }
        }

        // ── StatusBadge (adapted from ZeloServerVerwaltung) ───────────────────
        class StatusBadge : Control
        {
            public enum BMode { Entra, Joined, None, Working }
            BMode _mode; float _phase, _spin;
            public BMode Mode { get => _mode; set { _mode = value; Invalidate(); } }
            public StatusBadge() { SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true); Size = new Size(230, 28); BackColor = Color.White; }
            public void Tick(float ph, float sp) { _phase = ph; _spin = sp; if (_mode != BMode.None) Invalidate(); }
            protected override void OnPaint(PaintEventArgs e)
            {
                var g = e.Graphics; g.SmoothingMode = SmoothingMode.AntiAlias; g.TextRenderingHint = TextRenderingHint.ClearTypeGridFit; g.Clear(Color.White);
                Color bg; string txt;
                switch (_mode) {
                    case BMode.Joined:  bg = ColorTranslator.FromHtml("#059669"); txt = "DOMAIN JOINED"; break;
                    case BMode.Entra:   bg = ColorTranslator.FromHtml("#0D9488"); txt = "ENTRA ID JOINED"; break;
                    case BMode.Working: bg = ColorTranslator.FromHtml("#D97706"); txt = "BITTE WARTEN..."; break;
                    default:            bg = ColorTranslator.FromHtml("#6B7280"); txt = "WORKGROUP"; break;
                }
                int r = Height / 2;
                using (var path = new GraphicsPath()) { path.AddArc(0, 0, r * 2, r * 2, 90, 180); path.AddArc(Width - r * 2, 0, r * 2, r * 2, 270, 180); path.CloseFigure(); using (var br = new SolidBrush(bg)) g.FillPath(br, path); }
                // Dot
                int dx = r, dy = r, dr = 5;
                if (_mode == BMode.Working) { using (var p2 = new Pen(Color.FromArgb(60, Color.White), 2f)) g.DrawEllipse(p2, dx - dr, dy - dr, dr * 2, dr * 2); using (var p2 = new Pen(Color.White, 2f) { StartCap = LineCap.Round, EndCap = LineCap.Round }) g.DrawArc(p2, dx - dr, dy - dr, dr * 2, dr * 2, _spin, 100f); }
                else { double pv = Math.Sin(_phase * Math.PI * 2) * 0.5 + 0.5; int gr = dr + (int)(pv * 2); using (var b = new SolidBrush(Color.FromArgb(60, Color.White))) g.FillEllipse(b, dx - gr, dy - gr, gr * 2, gr * 2); using (var b = new SolidBrush(Color.White)) g.FillEllipse(b, dx - dr, dy - dr, dr * 2, dr * 2); }
                // Text
                var rect = new RectangleF(r * 2 + 6, 0, Width - r * 2 - 6 - r, Height);
                var sf = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center };
                using (var f = new Font("Segoe UI", 8.5f, FontStyle.Bold)) using (var br = new SolidBrush(Color.White)) g.DrawString(txt, f, br, rect, sf);
            }
        }
    }
}
