#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
dublicate.txt -> username set (ilk ':' öncesi)
saglamlar.txt içindeki aynı username'e sahip satırları SİLER (in-place).
- Hiç onay istemez
- saglamlar.txt.bak yedeği alır
- Encoding'i otomatik dener (utf-8, utf-8-sig, utf-16, utf-16-le, utf-16-be, cp1254, latin-1)
- Büyük dosyalar için streaming + temp dosya
"""

from pathlib import Path
import shutil
import sys
import tempfile

DUP_NAMES   = ["dublicate.txt", "duplicate.txt"]  # her ihtimale karşı
TARGET_NAME = "saglamlar.txt"
TRY_ENCODINGS = ["utf-8", "utf-8-sig", "utf-16", "utf-16-le", "utf-16-be", "cp1254", "latin-1"]

def extract_user(line: str) -> str:
    # ilk ':' öncesini username say
    return (line.split(":", 1)[0] if ":" in line else line).strip()

def find_first(*names: str) -> Path | None:
    cwd = Path.cwd()
    try:
        script_dir = Path(__file__).resolve().parent
    except NameError:
        script_dir = cwd
    for root in (cwd, script_dir):
        for n in names:
            p = root / n
            if p.is_file():
                return p
    return None

def try_read_lines(path: Path):
    # satırları ve kullanılan encoding'i döndürür
    for enc in TRY_ENCODINGS:
        try:
            with path.open("r", encoding=enc, errors="strict", newline="") as f:
                lines = f.readlines()
            if lines or path.stat().st_size == 0:
                return lines, enc
        except Exception:
            continue
    # son çare: latin-1 replace ile
    text = path.read_bytes().decode("latin-1", errors="replace")
    return text.splitlines(keepends=True), "latin-1(replace)"

def iter_lines(path: Path):
    # streaming okuma için uygun encoding'i bulup iterator döndür
    last_err = None
    for enc in TRY_ENCODINGS:
        try:
            f = path.open("r", encoding=enc, errors="strict", newline="")
            first_chunk = f.readline()
            if first_chunk == "" and path.stat().st_size > 0:
                # boş satır ama dosya boş değilse bu encoding olmayabilir
                f.close()
                continue
            # geri sar ve iterator ver
            f.seek(0)
            return f, enc
        except Exception as e:
            last_err = e
            continue
    # son çare
    raise SystemExit(f"[HATA] {path} okunamadı. Son hata: {last_err}")

def main():
    dup_path = find_first(*DUP_NAMES)
    if not dup_path:
        raise SystemExit(f"[HATA] duplicate dosyası bulunamadı. Aranan adlar: {', '.join(DUP_NAMES)}")

    target_path = find_first(TARGET_NAME)
    if not target_path:
        raise SystemExit(f"[HATA] Hedef dosya bulunamadı: {TARGET_NAME}")

    # duplicate'i oku -> username set
    dup_lines, dup_enc = try_read_lines(dup_path)
    dup_users = {extract_user(l.strip()) for l in dup_lines if l.strip()}
    print(f"[INFO] duplicate: {dup_path} | enc: {dup_enc} | usernames: {len(dup_users)}")

    # hedefi streaming oku, temp dosyaya yaz
    fin, target_enc = iter_lines(target_path)
    print(f"[INFO] hedef: {target_path} | enc: {target_enc}")

    # önce yedek al
    bak = target_path.with_suffix(target_path.suffix + ".bak")
    shutil.copy2(target_path, bak)
    print(f"[INFO] Yedek: {bak}")

    removed = 0
    kept = 0
    with fin:
        with tempfile.NamedTemporaryFile("w", delete=False, encoding="utf-8", newline="") as fout:
            tmp_path = Path(fout.name)
            for raw in fin:
                user = extract_user(raw)
                if user and user in dup_users:
                    removed += 1
                    continue
                kept += 1
                fout.write(raw)

    # temp'i hedefin üstüne al
    shutil.move(str(tmp_path), str(target_path))
    print(f"[OK] Silinen: {removed} | Kalan: {kept} | Güncellendi: {target_path}")
    print(f"[NOT] Geri almak için: {bak}")

if __name__ == "__main__":
    try:
        main()
    except SystemExit as e:
        print(e)
        if sys.stdin and sys.stdin.isatty():
            input("\nDevam etmek için Enter...")
        raise
