#include "lisans_yukle.hpp"

#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <ctime>
#include <filesystem>
#include <fstream>
#include <sstream>

#if defined(_WIN32)
#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <shellapi.h>  // ShellExecuteW (mailto: varsayılan e-posta istemcisi)
#endif

#include "ayar_kalici.hpp"     // ayarOku/ayarYaz (saat geri alma damgası)
#include "ayar_kayitlari.hpp"  // lisansZorunlu()
#include "fiko/cekirdek/gecici.hpp"
#include "fiko/cekirdek/lisans.hpp"
#include "fiko/cekirdek/lisans_sayac.hpp"  // merkezi (cihaz geneli) kota sayacı
#include "fiko/cekirdek/makine_kimlik.hpp"
#include "fiko/core/gunluk.hpp"
#include "fiko/ui/bilesen_ek.hpp"  // ui::toastGoster (kaydet/e-posta geri bildirimi)
#include "fiko/ui/tema.hpp"  // ui::tema (ayar sayfası renkleri)
#include "imgui.h"

namespace fs = std::filesystem;

namespace fiko {
namespace {

// ── Lisans imza açık anahtarı (ECDSA P-256, X||Y = 64 bayt hex) ──────────────
// Sürüm-paketi anahtarından (guncelleme_indir.cpp) AYRI bir çifttir. Eşi olan özel
// anahtar YALNIZ üretici makinede: %USERPROFILE%\.fikoyt\lisans_ozel.key — depoya
// asla girmez. Boş bırakılırsa hiçbir lisans doğrulanamaz (sessiz bypass yasak).
// Bu anahtarı değiştirmek DAHA ÖNCE KESİLMİŞ TÜM LİSANSLARI geçersiz kılar.
constexpr const char* LISANS_ACIK_ANAHTAR_HEX =
    "605dbff7195ed0906efb3aaf618f1f788c83908cec75c4ca4c1811be68fb5188"
    "35b9c053533be019f7483a78428241b995c74e3b988610032ef2acd5fe42f502";

// Lisans taleplerinin gideceği adres ("✉ E-posta ile gönder" düğmesi). Satıcı/bayi
// dağıtımında burayı değiştirmek yeter — başka yerde gömülü adres yok.
constexpr const char* SATICI_EPOSTA = "lisans@fikoyt.com";

LisansOturum g_oturum;
bool g_yuklendi = false;

std::string dosyaOku(const fs::path& p) {
  std::ifstream f(p, std::ios::binary);
  if (!f) return "";
  std::ostringstream ss;
  ss << f.rdbuf();
  // Şifreli (FKLE1) zarfı aç; düz metin lisanslar aynen geri döner (geriye uyum).
  u8 zarfAnahtar[32];
  lisansZarfAnahtari(zarfAnahtar);
  return lisansZarfCoz(ss.str(), zarfAnahtar);
}

}  // namespace

LisansSistemi& lisansSistemi() {
  static LisansSistemi s;
  return s;
}

namespace {

// Görüntüleyici (salt-okunur) kipi — lisans YOK / GEÇERSİZ / SÜRESİ DOLMUŞ / BAŞKA
// MAKİNE / YAMALI YAPI hâllerinin ORTAK sonucu. Tek yerde tanımlı: bir kanalı
// unutmak = o durumda gizmoyla modelleme açık kalması demek (yaşandı).
void goruntuleyiciKipiUygula(LisansSistemi& sis) {
  //  • dosya.yeni/ac/kaydet → kendi .fikocad çalışmanı açıp kaydet (veri rehin kalmaz)
  //  • gorunum/secim/olcum → aç, döndür, incele, ölç
  //  • arac.komut_denetim → ⚠️ ZORUNLU: lisans penceresi; kapatırsak kullanıcı kendini
  //    dışarı kilitler. WTEC kafa (arac.diagonal_kafa|ozmo_kafa) KASITLI yok.
  // STEP/APT/WebCAD/mesh içe-dışa aktarma ÜCRETLİDİR (listede yok).
  static const char* const IZINLI[] = {
      "dosya.yeni",   "dosya.ac",        "dosya.kaydet",        "dosya.olay_gunluk",
      "gorunum.*",    "secim.*",         "olcum.*",             "arac.komut_denetim",
      "arac.ayarlar", "arac.guncelleme", "arac.gecici_temizle", "arac.geri_bildirim",
      // Üretim aracı: müşteride komut zaten KAYDEDİLMEZ (lisansUreticiModu), o yüzden
      // burada izinli olması müşteriye bir şey açmaz. Bizde ise ZORUNLU: lisans dosyası
      // yokken (tam da lisans üretmemiz gereken an) üreticinin gizlenmesi kilitlenmedir.
      "arac.lisans_uretici",
  };
  sis.politikaSifirla();  // önceki (kısmen uygulanmış) lisans politikasını temizle
  sis.kipAyarla(LisansSistemi::Kip::Kisitli);
  for (const char* g : {"Dosya", "Görünüm", "Seçim", "Ölçüm", "Araçlar", "Yardım"})
    sis.grupIzinVer(g);
  for (const char* k : IZINLI) sis.komutIzinVer(k);
  sis.saltOkunurAyarla(true);
}

// ---- Saat geri alma koruması ----
// Offline lisansın klasik açığı: kullanıcı sistem saatini geri alıp süresi dolmuş
// lisansı yeniden çalıştırır. Her açılışta gördüğümüz EN BÜYÜK zaman kalıcı ayara
// yazılır; şimdiki zaman ondan belirgin ölçüde geriyse saat oynanmış demektir.
// Tolerans 1 gün: saat dilimi/yaz saati/NTP düzeltmesi meşru küçük geri gidişler yapar.
constexpr i64 SAAT_TOLERANS = 86400;
constexpr const char* SON_ZAMAN_ANAHTAR = "lisans_son_zaman";

bool saatGeriAlinmisMi(i64 suan) {
  const std::string kayit = ayarOku(SON_ZAMAN_ANAHTAR, "");
  const i64 sonGorulen = kayit.empty() ? 0 : std::strtoll(kayit.c_str(), nullptr, 10);
  const bool geri = sonGorulen != 0 && suan + SAAT_TOLERANS < sonGorulen;
  if (suan > sonGorulen) ayarYaz(SON_ZAMAN_ANAHTAR, std::to_string(suan));  // ileri = normal
  return geri;
}

// "12.05.2027" — bitiş damgasını okunur tarihe çevirir (0 → "süresiz").
std::string tarihMetni(i64 unix) {
  if (unix == 0) return "süresiz";
  const std::time_t t = (std::time_t)unix;
  std::tm tm{};
  char buf[32] = "?";
  if (localtime_s(&tm, &t) == 0) std::strftime(buf, sizeof(buf), "%d.%m.%Y", &tm);
  return buf;
}

// ── Müşteri parmak izi paylaşımı (lisans talebi) ────────────────────────────
// Müşteri lisans alabilmek için makine kimliğini satıcıya iletmek zorunda. Bu
// yardımcılar o tek adımı üç ayrı kanaldan (pano / dosya / e-posta) kolaylaştırır;
// hepsi AYNI metni üretir ki satıcıya ulaşan bilgi kanala göre değişmesin.

// "20.07.2026 14:33" — belge başlığı için.
std::string simdiMetni() {
  const std::time_t t = std::time(nullptr);
  std::tm tm{};
  char buf[32] = "?";
  if (localtime_s(&tm, &t) == 0) std::strftime(buf, sizeof(buf), "%d.%m.%Y %H:%M", &tm);
  return buf;
}

// Ekranda okunur kısaltma: ilk 8 … son 4. Tam değer tooltip'te gösterilir.
std::string kisaHash(const std::string& h) {
  if (h.size() <= 16) return h;
  return h.substr(0, 8) + "…" + h.substr(h.size() - 4);
}

// Lisans dosyasına birebir girecek satırlar. `yapiDahil` → sürüme bağlı lisans için
// `yapi=` satırı da eklenir (panoya kopyalama eski davranışı korur: yalnız makine=).
std::string parmakIziSatirlari(bool yapiDahil) {
  const MakineParmakIzi& p = makineParmakIzi();
  std::string s;
  for (const std::string* h : {&p.kurulum, &p.disk, &p.cpu, &p.bios})
    if (!h->empty()) s += "makine=" + *h + "\n";
  if (yapiDahil && !uygulamaYapiHash().empty()) s += "yapi=" + uygulamaYapiHash() + "\n";
  return s;
}

// Masaüstüne kaydedilen/e-postaya giren tam belge. Müşteri ne gönderdiğini anlasın
// diye başlık + açıklama var; satıcı ise yalnız `makine=`/`yapi=` satırlarını alır.
std::string makineKimlikBelgesi() {
  std::string s = "FikoCAD — makine kimliği (lisans talebi)\n";
  s += "Oluşturma      : " + simdiMetni() + "\n";
  if (const char* cn = std::getenv("COMPUTERNAME"); cn && *cn)
    s += "Bilgisayar adı : " + std::string(cn) + "\n";
  if (const char* un = std::getenv("USERNAME"); un && *un)
    s += "Kullanıcı      : " + std::string(un) + "\n";
  s += "\n--- Aşağıdaki satırları satıcınıza gönderin ---\n";
  s += parmakIziSatirlari(true);
  s += "\nBu bilgi yalnız bu bilgisayarı tanır; kişisel veri içermez ve donanım\n"
       "bilgileri geri çevrilemez biçimde özetlenmiştir. Lisansınız bu bilgiye göre\n"
       "hazırlanır ve yalnız bu bilgisayarda çalışır.\n";
  return s;
}

// Masaüstü (%USERPROFILE%\Desktop); yoksa exe yanı — kayıt hiçbir hâlde kaybolmasın.
fs::path masaustuYolu() {
  std::error_code ec;
  if (const char* up = std::getenv("USERPROFILE"); up && *up) {
    const fs::path d = fs::path(up) / "Desktop";
    if (fs::is_directory(d, ec)) return d;
  }
  return gecici::uygulamaDizini();
}

#if defined(_WIN32)
std::wstring genisMetin(const std::string& s) {
  const int n = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0);
  std::wstring w(n > 0 ? (std::size_t)(n - 1) : 0, L'\0');
  if (n > 1) MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, w.data(), n);
  return w;
}
#endif

// mailto: gövdesi için yüzde kodlama. Satır sonu CRLF olmalı (%0D%0A) — tek %0A'yı
// bazı istemciler yok sayar ve tüm parmak izi tek satıra yapışır.
std::string urlKodla(const std::string& s) {
  static const char HEX[] = "0123456789ABCDEF";
  std::string c;
  c.reserve(s.size() * 3);
  for (const unsigned char ch : s) {
    if (std::isalnum(ch) || ch == '-' || ch == '_' || ch == '.' || ch == '~') {
      c += (char)ch;
    } else if (ch == '\r') {
      continue;
    } else if (ch == '\n') {
      c += "%0D%0A";
    } else {
      c += '%';
      c += HEX[ch >> 4];
      c += HEX[ch & 0x0F];
    }
  }
  return c;
}

// Varsayılan e-posta istemcisinde hazır taslak açar. Uzun mailto URL'lerini kimi
// istemci/kabuk kırptığı için ~1900 karakteri aşarsa gövde yalnız hash satırlarına
// indirilir (bilgi kaybı yok — satıcının ihtiyacı olan kısım zaten o).
bool epostaIleGonder(std::string& mesaj) {
#if defined(_WIN32)
  const std::string bas = "mailto:" + std::string(SATICI_EPOSTA) +
                          "?subject=" + urlKodla("FikoCAD lisans talebi") + "&body=";
  const std::string govde =
      "Merhaba,\n\nFikoCAD lisansı almak istiyorum. Bilgisayarımın kimliği aşağıdadır:\n\n" +
      parmakIziSatirlari(true) + "\nTeşekkürler.\n";
  std::string url = bas + urlKodla(govde);
  if (url.size() > 1900) url = bas + urlKodla(parmakIziSatirlari(true));

  const HINSTANCE r =
      ShellExecuteW(nullptr, L"open", genisMetin(url).c_str(), nullptr, nullptr, SW_SHOWNORMAL);
  if ((INT_PTR)r <= 32) {
    gunluk::uyari("Lisans talebi e-postası açılamadı (ShellExecute {})", (INT_PTR)r);
    mesaj = "E-posta uygulaması açılamadı — 'Panoya kopyala' ile alıp elle gönderin.";
    return false;
  }
  mesaj = std::string("E-posta taslağı açıldı: ") + SATICI_EPOSTA;
  return true;
#else
  mesaj = "E-posta gönderimi yalnız Windows'ta desteklenir — 'Dosyaya kaydet' kullanın.";
  return false;
#endif
}

}  // namespace

bool lisansSaglikKontrol() {
  if (lisansSistemi().saglikKontrol()) return true;
  gunluk::uyari("Lisans politikası bütünlüğü bozuldu — kısıtlı kipe geçildi");
  return false;
}

bool surukleBirakIzinli(const std::string& yol) {
  const std::size_t nokta = yol.find_last_of('.');
  std::string uz = nokta == std::string::npos ? "" : yol.substr(nokta + 1);
  for (char& c : uz) c = (char)std::tolower((unsigned char)c);

  // Uzantı → gereken komut hakkı (menüden açarken hangi komut çalışacaksa o).
  const char* kimlik = nullptr;
  if (uz == "fikocad")                              kimlik = "dosya.ac";
  else if (uz == "step" || uz == "stp" || uz == "iges" || uz == "igs" || uz == "brep" ||
           uz == "stl" || uz == "obj")              kimlik = "dosya.step_ice";
  else if (uz == "fikoapt" || uz == "apt")          kimlik = "dosya.apt_ac";
  else if (uz == "fikoop" || uz == "wrl")           kimlik = "dosya.webcad_ac";
  if (!kimlik) return true;  // tanımadığımız uzantı: eski davranış (yolAc karar verir)

  // Grup adı gate'in ikinci ekseni; bu kimliklerin hepsi "Dosya" grubunda.
  return lisansSistemi().ogeGorunur(kimlik, "Dosya");
}

std::vector<std::string> lisansAranacakYollar() {
  std::vector<std::string> yollar;
  if (const char* env = std::getenv("FIKO_LISANS")) {
    if (*env) yollar.push_back(env);
  }
  yollar.push_back((gecici::uygulamaDizini() / "lisans.fkl").string());
  const char* pd = std::getenv("ProgramData");
  if (pd && *pd) yollar.push_back((fs::path(pd) / "FikoCAD" / "lisans.fkl").string());

  // ÇOKLU LİSANS: `lisanslar/` dizinindeki TÜM .fkl dosyaları da yüklenir. Müşteri
  // sonradan paket satın alınca ikinci dosyayı buraya bırakır — eskisi bozulmaz,
  // haklar BİRLEŞİR. Her dosya ayrı ayrı imza + makine doğrulamasından geçer.
  std::error_code ec;
  std::vector<fs::path> kokler{gecici::uygulamaDizini() / "lisanslar"};
  if (pd && *pd) kokler.push_back(fs::path(pd) / "FikoCAD" / "lisanslar");
  for (const fs::path& kok : kokler) {
    if (!fs::is_directory(kok, ec)) continue;
    std::vector<std::string> bulunan;  // sıralı: her açılışta aynı sıra → aynı politika
    for (const auto& g : fs::directory_iterator(kok, ec)) {
      if (g.is_regular_file(ec) && g.path().extension() == ".fkl")
        bulunan.push_back(g.path().string());
    }
    std::sort(bulunan.begin(), bulunan.end());
    yollar.insert(yollar.end(), bulunan.begin(), bulunan.end());
  }
  return yollar;
}

const LisansOturum& lisansYukleVeUygula(LisansSistemi& sis) {
  g_yuklendi = true;
  g_oturum = LisansOturum{};
  g_oturum.zorunlu = lisansZorunlu();

  // Merkezi kota sayacı (cihaz geneli, süreçler arası). BİR KEZ bağlanır: ikinci
  // fikocad süreci ve yeni belge pencereleri AYNI sayacı görür.
  static bool sayacBagli = false;
  if (!sayacBagli) {
    sis.sayacDeposuAyarla(lisansSayacDeposu(
        /*kok*/ "", [] { return ayarOku("lisans_kota", ""); },
        [](const std::string& s) { ayarYaz("lisans_kota", s); }));
    sayacBagli = true;
  }

  // ---- ÇOKLU LİSANS: bulunan TÜM .fkl dosyaları yüklenir, haklar BİRLEŞİR ----
  // Her dosya ayrı ayrı imza + makine + yapı doğrulamasından geçer; biri geçersizse
  // yalnız o atlanır (diğerleri çalışmaya devam eder). En az biri geçerliyse oturum
  // geçerlidir.
  const i64 suan = (i64)std::time(nullptr);
  g_oturum.saatGeriAlinmis = saatGeriAlinmisMi(suan);
  const std::vector<std::string> yerel = makineParmakIzi().hashListesi();

  // ÜRETİM KAZASI KORUMASI: anahtar gömülmeden sürüm çıkarsa HİÇBİR lisans doğrulanamaz
  // (her müşteri görüntüleyici kipine düşer). Sessiz kalmasın — günlük + panel uyarısı.
  if (LISANS_ACIK_ANAHTAR_HEX[0] == '\0') {
    gunluk::uyari(
        "Lisans açık anahtarı GÖMÜLMEMİŞ (lisans_yukle.cpp) — hiçbir lisans doğrulanamaz. "
        "Üretim sürümü için 'fiko_lisans anahtar' çıktısındaki açık anahtarı göm.");
  }

  sis.politikaSifirla();  // her yüklemede temiz başla
  int gecerliSayi = 0;
  for (const std::string& y : lisansAranacakYollar()) {
    const std::string metin = dosyaOku(y);
    if (metin.empty()) continue;
    LisansBilgi bilgi;
    std::string hata;
    LisansDurum d = lisansCoz(metin, LISANS_ACIK_ANAHTAR_HEX, bilgi, hata);
    if (d == LisansDurum::Gecerli) {
      d = lisansUygula(bilgi, sis, yerel, suan, /*birlestir*/ gecerliSayi > 0);
      // Saat geri alınmışsa SÜRELİ lisans geçersiz sayılır (süresiz etkilenmez).
      if (g_oturum.saatGeriAlinmis && bilgi.bitis != 0 && d == LisansDurum::Gecerli) {
        d = LisansDurum::SuresiDolmus;
        gunluk::uyari("Sistem saati geri alınmış — süreli lisans geçersiz sayıldı: {}", y);
      }
    }
    if (d == LisansDurum::Gecerli) {
      if (gecerliSayi == 0) {  // ilk geçerli lisans "ana" bilgi (özet/panel onu gösterir)
        g_oturum.bilgi = bilgi;
        g_oturum.yol = y;
        for (const std::string& yy : yerel)
          for (const std::string& m : bilgi.makineHashleri)
            if (yy == m) ++g_oturum.eslesenAlan;
      }
      ++gecerliSayi;
      g_oturum.lisanslar.push_back(
          {y, bilgi.seri, bilgi.musteri, bilgi.bitis, (int)bilgi.paketler.size()});
      gunluk::bilgi("Lisans yüklendi: {} ({})", bilgi.seri, y);
    } else {
      g_oturum.hata = hata.empty() ? lisansDurumMetni(d) : hata;
      if (g_oturum.yol.empty()) g_oturum.yol = y;
      g_oturum.durum = d;
      gunluk::uyari("Lisans atlandı ({}): {}", lisansDurumMetni(d), y);
    }
  }

  if (gecerliSayi > 0) {
    g_oturum.durum = LisansDurum::Gecerli;
  } else {
    if (g_oturum.durum == LisansDurum::Gecerli) g_oturum.durum = LisansDurum::Bos;
    if (g_oturum.hata.empty()) g_oturum.hata = "Lisans dosyası bulunamadı";
    if (g_oturum.zorunlu) goruntuleyiciKipiUygula(sis);
    else sis.politikaSifirla();  // zorunlu değil → hiçbir kısıt (geliştirme yapısı)
  }
  gunluk::bilgi("Lisans durumu: {} ({} dosya geçerli)", lisansDurumMetni(g_oturum.durum),
                gecerliSayi);
  return g_oturum;
}

const LisansOturum& lisansOturum() { return g_oturum; }

bool lisansYuklendiMi() { return g_yuklendi; }

int LisansOturum::kalanGun() const {
  if (bilgi.bitis == 0) return -1;  // süresiz
  const i64 fark = bilgi.bitis - (i64)std::time(nullptr);
  return fark <= 0 ? 0 : (int)(fark / 86400);
}

std::string lisansOzet() {
  if (g_oturum.gecerliMi()) {
    std::string s = "Lisanslı";
    if (!g_oturum.bilgi.musteri.empty()) s += " — " + g_oturum.bilgi.musteri;
    if (g_oturum.lisanslar.size() > 1) {
      s += " (" + std::to_string(g_oturum.lisanslar.size()) + " lisans dosyası)";
    } else if (!g_oturum.bilgi.komutlar.empty() || !g_oturum.bilgi.paketler.empty()) {
      s += " (" + std::to_string(g_oturum.bilgi.komutlar.size()) + " komut, " +
           std::to_string(g_oturum.bilgi.paketler.size()) + " paket)";
    }
    return s;
  }
  return std::string(g_oturum.zorunlu ? "Lisanssız — görüntüleyici kipi: "
                                      : "Lisanssız (serbest): ") +
         (g_oturum.hata.empty() ? "?" : g_oturum.hata);
}

void lisansAyarBolumu() {
  const LisansOturum& o = lisansOturum();
  const LisansSistemi& sis = lisansSistemi();
  const ui::Tema& tm = ui::tema();

  ImGui::Spacing();
  ImGui::SeparatorText("Lisans durumu");
  ImGui::TextColored(o.gecerliMi() ? ImVec4(0.35f, 0.85f, 0.45f, 1)
                                   : ImVec4(0.95f, 0.65f, 0.25f, 1),
                     "%s", lisansOzet().c_str());
  if (o.gecerliMi()) {
    ImGui::Text("Seri: %s", o.bilgi.seri.c_str());
    ImGui::SameLine();
    if (const int gun = o.kalanGun(); gun >= 0) {
      ImGui::TextColored(gun <= 30 ? ImVec4(1.0f, 0.65f, 0.25f, 1) : tm.metinSoluk,
                         "   Bitiş: %s (%d gün)", tarihMetni(o.bilgi.bitis).c_str(), gun);
    } else {
      ImGui::TextDisabled("   Süresiz");
    }
    if (!o.bilgi.makineHashleri.empty())
      ImGui::TextDisabled("Makine: %d/%d alan eşleşti (gereken %d)", o.eslesenAlan,
                          (int)o.bilgi.makineHashleri.size(), o.bilgi.makineTolerans);
    if (o.saatGeriAlinmis)
      ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.35f, 1), "⚠ Sistem saati geri alınmış");
  }

  // ---- Yüklü lisans dosyaları (çoklu lisans: haklar birleşir) ----
  if (o.lisanslar.size() > 1 && ImGui::TreeNode("Yüklü lisans dosyaları")) {
    for (const auto& d : o.lisanslar) {
      ImGui::BulletText("%s — %s (%s, %d paket)", d.seri.c_str(), d.musteri.c_str(),
                        tarihMetni(d.bitis).c_str(), d.paketSayi);
      if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", d.yol.c_str());
    }
    ImGui::TreePop();
  }

  // ---- Paketler: her biri kendi bitişi + içerdiği komut desenleriyle ----
  if (!o.bilgi.paketler.empty()) {
    ImGui::SeparatorText("Paketler");
    if (ImGui::BeginTable("lisansPaket", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
      ImGui::TableSetupColumn("Paket");
      ImGui::TableSetupColumn("Bitiş", ImGuiTableColumnFlags_WidthFixed, 130);
      ImGui::TableSetupColumn("Komut", ImGuiTableColumnFlags_WidthFixed, 60);
      ImGui::TableHeadersRow();
      const i64 suan = (i64)std::time(nullptr);
      for (const LisansPaket& p : o.bilgi.paketler) {
        ImGui::TableNextRow();
        ImGui::TableSetColumnIndex(0);
        ImGui::TextUnformatted(p.ad.empty() ? p.kimlik.c_str() : p.ad.c_str());
        if (ImGui::IsItemHovered() && !p.komutlar.empty()) {
          std::string liste;
          for (const std::string& k : p.komutlar) liste += k + "\n";
          ImGui::SetTooltip("%s", liste.c_str());
        }
        ImGui::TableSetColumnIndex(1);
        const bool dolmus = p.bitis != 0 && suan > p.bitis;
        ImGui::TextColored(dolmus ? ImVec4(1.0f, 0.4f, 0.35f, 1) : tm.metin, "%s%s",
                           tarihMetni(p.bitis).c_str(), dolmus ? "  (doldu)" : "");
        ImGui::TableSetColumnIndex(2);
        ImGui::Text("%d", (int)p.komutlar.size());
      }
      ImGui::EndTable();
    }
  }

  // ---- Kotalar: dönem + kullanılan/limit + kalan ----
  const auto& kurallar = sis.kotaKurallari();
  if (!kurallar.empty()) {
    ImGui::SeparatorText("Kullanım hakları (kota)");
    if (ImGui::BeginTable("lisansKota", 4, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
      ImGui::TableSetupColumn("Komut");
      ImGui::TableSetupColumn("Dönem", ImGuiTableColumnFlags_WidthFixed, 70);
      ImGui::TableSetupColumn("Kullanım", ImGuiTableColumnFlags_WidthFixed, 80);
      ImGui::TableSetupColumn("Kalan", ImGuiTableColumnFlags_WidthFixed, 60);
      ImGui::TableHeadersRow();
      for (const auto& k : kurallar) {
        ImGui::TableNextRow();
        ImGui::TableSetColumnIndex(0);
        ImGui::TextUnformatted(k.desen.c_str());
        if (!k.paket.empty() && ImGui::IsItemHovered())
          ImGui::SetTooltip("Paket: %s", k.paket.c_str());
        ImGui::TableSetColumnIndex(1);
        ImGui::TextUnformatted(kotaPeriyotMetni(k.periyot).c_str());
        ImGui::TableSetColumnIndex(2);
        ImGui::Text("%llu / %llu", (unsigned long long)sis.kotaKullanim(k),
                    (unsigned long long)k.limit);
        ImGui::TableSetColumnIndex(3);
        const u64 kalan = sis.kotaKalan(k);
        ImGui::TextColored(kalan == 0 ? ImVec4(1.0f, 0.4f, 0.35f, 1) : tm.metin, "%llu",
                           (unsigned long long)kalan);
      }
      ImGui::EndTable();
    }
    ImGui::TextColored(tm.metinSoluk,
                       "Sayaçlar CİHAZ GENELİ: tüm pencereler ve süreçler aynı hakkı paylaşır.\n"
                       "Dönem penceresi değişince sıfırlanır.");
  }
}

void lisansDurumBolumu(LisansSistemi& sis, Cekirdek& cek) {
  static std::string sonIslem;  // son dışa aktarma/yeniden yükleme sonucu
  const LisansOturum& o = lisansOturum();

  ImGui::SeparatorText("Lisans");
  if (LISANS_ACIK_ANAHTAR_HEX[0] == '\0') {
    ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.35f, 1),
                       "⚠ Açık anahtar gömülmemiş — lisans doğrulama DEVRE DIŞI");
    if (ImGui::IsItemHovered())
      ImGui::SetTooltip("Geliştirme yapısı. Üretim için: fiko_lisans anahtar → çıkan\n"
                        "açık anahtarı lisans_yukle.cpp içine göm, özel anahtarı sakla.");
  }
  const bool ok = o.gecerliMi();
  ImGui::TextColored(ok ? ImVec4(0.35f, 0.85f, 0.45f, 1) : ImVec4(0.95f, 0.65f, 0.25f, 1), "%s",
                     lisansOzet().c_str());
  if (!o.yol.empty()) {
    ImGui::TextDisabled("Dosya: %s", o.yol.c_str());
  } else {
    ImGui::TextDisabled("Aranan: %s", lisansAranacakYollar().front().c_str());
  }
  if (ok) {
    if (!o.bilgi.seri.empty()) ImGui::Text("Seri: %s", o.bilgi.seri.c_str());
    if (const int gun = o.kalanGun(); gun >= 0) {
      const bool yakin = gun <= 30;
      ImGui::TextColored(yakin ? ImVec4(1.0f, 0.65f, 0.25f, 1) : ImVec4(0.7f, 0.7f, 0.7f, 1),
                         "Kalan süre: %d gün%s", gun, yakin ? "  ⚠ yenileme zamanı" : "");
    } else {
      ImGui::TextDisabled("Süresiz lisans");
    }
    if (o.saatGeriAlinmis)
      ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.35f, 1), "⚠ Sistem saati geri alınmış");
    if (!o.bilgi.makineHashleri.empty())
      ImGui::Text("Makine: %d/%d alan eşleşti (gereken %d)", o.eslesenAlan,
                  (int)o.bilgi.makineHashleri.size(), o.bilgi.makineTolerans);
  }

  // ── Makine kimliği: müşterinin lisans alabilmesi için TEK adım ─────────────
  // Lisans yokken bu bölüm müşterinin yapması gereken TEK iş — o yüzden kendiliğinden
  // açılır ve başlığı eylem söyler. Lisans varken nötr başlıkla kapalı durur.
  // ⚠️ Bu pencere görüntüleyici kipinde de açıktır (arac.komut_denetim izinli) —
  // lisanssız müşteri buraya erişemezse kendini dışarı kilitler.
  if (!ok) ImGui::SetNextItemOpen(true, ImGuiCond_Once);
  if (ImGui::TreeNodeEx("makineKimligi", ImGuiTreeNodeFlags_SpanAvailWidth, "%s",
                        ok ? "Bu makinenin kimliği (parmak izi)"
                           : "🔑 Lisans almak için: bu makinenin kimliği")) {
    ImGui::TextWrapped(
        "Aşağıdaki bilgiyi kopyalayıp satıcınıza gönderin.\n"
        "Lisansınız yalnız bu bilgisayarda çalışacak şekilde hazırlanır.\n"
        "Bu bilgide kişisel veri yoktur.");
    ImGui::Spacing();

    const MakineParmakIzi& p = makineParmakIzi();
    std::string panoMetni;  // eski davranış: panoya YALNIZ makine= satırları
    for (const auto& [ad, h] : {std::pair{"kurulum", p.kurulum}, std::pair{"disk", p.disk},
                                std::pair{"cpu", p.cpu}, std::pair{"bios", p.bios}}) {
      ImGui::TextDisabled("%-9s", ad);
      ImGui::SameLine();
      ImGui::TextUnformatted(h.empty() ? "(okunamadı)" : kisaHash(h).c_str());
      if (!h.empty()) {
        if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", h.c_str());
        panoMetni += std::string("makine=") + h + "\n";
      }
    }
    ImGui::TextDisabled("%-9s", "yapi");
    ImGui::SameLine();
    ImGui::TextUnformatted(kisaHash(uygulamaYapiHash()).c_str());
    if (ImGui::IsItemHovered()) ImGui::SetTooltip("%s", uygulamaYapiHash().c_str());
    ImGui::SameLine();
    ImGui::TextDisabled("(sürüme bağlı lisans için)");
    ImGui::Spacing();

    if (ImGui::Button("📋 Panoya kopyala")) {
      ImGui::SetClipboardText(panoMetni.c_str());
      sonIslem = "Makine kimliği panoya kopyalandı — satıcınıza yapıştırıp gönderin.";
      ui::toastGoster("Makine kimliği panoya kopyalandı", ui::ToastTip::Basari);
    }
    if (ImGui::IsItemHovered())
      ImGui::SetTooltip("Lisans satırlarını panoya alır; mesaj/e-postaya yapıştırabilirsiniz.");

    ImGui::SameLine();
    if (ImGui::Button("💾 Dosyaya kaydet")) {
      const fs::path hedef = masaustuYolu() / "fikocad-makine-kimligi.txt";
      std::ofstream f(hedef, std::ios::binary);
      if (f) f << makineKimlikBelgesi();
      if (f) {
        f.close();
        sonIslem = "Makine kimliği kaydedildi: " + hedef.string();
        ui::toastGoster(("Kaydedildi: " + hedef.string()).c_str(), ui::ToastTip::Basari, 6.0f);
      } else {
        sonIslem = "Dosya yazılamadı: " + hedef.string();
        gunluk::uyari("Makine kimliği dosyası yazılamadı: {}", hedef.string());
        ui::toastGoster("Dosya yazılamadı — 'Panoya kopyala' kullanın", ui::ToastTip::Hata, 6.0f);
      }
    }
    if (ImGui::IsItemHovered())
      ImGui::SetTooltip("Masaüstüne 'fikocad-makine-kimligi.txt' yazar; dosyayı ekleyip yollayın.");

    ImGui::SameLine();
    if (ImGui::Button("✉ E-posta ile gönder")) {
      std::string mesaj;
      const bool basarili = epostaIleGonder(mesaj);
      sonIslem = mesaj;
      ui::toastGoster(mesaj.c_str(), basarili ? ui::ToastTip::Basari : ui::ToastTip::Hata, 6.0f);
    }
    if (ImGui::IsItemHovered())
      ImGui::SetTooltip("Varsayılan e-posta uygulamanızda hazır bir lisans talebi açar (%s).",
                        SATICI_EPOSTA);
    ImGui::TreePop();
  }

  // Satın alınan komut hakları (joker dahil).
  if (!o.bilgi.komutlar.empty() && ImGui::TreeNode("Satın alınan komutlar")) {
    for (const std::string& k : o.bilgi.komutlar) ImGui::BulletText("%s", k.c_str());
    ImGui::TreePop();
  }

  // Kilitli komutlar: menüde/toolbar'da GİZLİLER (satın alınmadılar) — ama burada
  // listelenirler ki kullanıcı ne alabileceğini görsün ve kimliği bize iletebilsin.
  if (ImGui::TreeNode("Kilitli komutlar (satın alınabilir)")) {
    int n = 0;
    if (ImGui::BeginTable("kilitli", 2,
                          ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
                              ImGuiTableFlags_ScrollY,
                          ImVec2(0, 180))) {
      ImGui::TableSetupColumn("Komut");
      ImGui::TableSetupColumn("Kimlik", ImGuiTableColumnFlags_WidthFixed, 150);
      ImGui::TableHeadersRow();
      for (const MenuOge& m : cek.menuler().tumKayit()) {
        const std::string kimlik = komutKimligi(m);
        if (sis.ogeGorunur(kimlik, m.grup)) continue;  // görünür = satın alınmış
        ++n;
        ImGui::TableNextRow();
        ImGui::TableSetColumnIndex(0);
        ImGui::Text("%s › %s", m.grup.c_str(), m.ad.c_str());
        ImGui::TableSetColumnIndex(1);
        ImGui::TextDisabled("%s", kimlik.c_str());
      }
      ImGui::EndTable();
    }
    if (n == 0) ImGui::TextDisabled("Kilitli komut yok — tüm haklar açık.");
    ImGui::TreePop();
  }

  if (ImGui::Button("Lisansı yeniden yükle")) {
    lisansYukleVeUygula(sis);
    sonIslem = "Lisans yeniden yüklendi: " + lisansOzet();
  }
  ImGui::SameLine();
  if (ImGui::Button("Katalog CSV")) {
    const fs::path hedef = gecici::uygulamaDizini() / "lisans_katalog.csv";
    std::ofstream f(hedef, std::ios::binary);
    if (f) {
      f << lisansKatalogCsv(cek.menuler());
      sonIslem = "Katalog yazıldı: " + hedef.string();
    } else {
      sonIslem = "Katalog yazılamadı: " + hedef.string();
    }
  }
  if (!sonIslem.empty()) ImGui::TextWrapped("%s", sonIslem.c_str());
}

}  // namespace fiko
