#!/usr/bin/env python
from __future__ import annotations

import argparse
import re
from pathlib import Path
from typing import Iterable, Optional

AUTH_TOKEN_RE = re.compile(r"auth_token\s*[:=]\s*[\"']?([^\"'\s;,&]+)", re.IGNORECASE)
BASE32_RE = re.compile(r"^[A-Z2-7]{16,64}$")
HEX_RE = re.compile(r"^[0-9a-fA-F]+$")


def looks_like_totp(value: str) -> bool:
    return bool(BASE32_RE.fullmatch(value)) and len(value) in (16, 32)


def looks_like_token(value: str) -> bool:
    if not value or len(value) < 8:
        return False
    if any(ch.isspace() for ch in value):
        return False
    if "@" in value or "|" in value:
        return False
    return True


def is_hex_len(value: str, length: int) -> bool:
    return len(value) == length and bool(HEX_RE.fullmatch(value))


def pick_auth_from_pair(a: str, b: str) -> str:
    if looks_like_totp(a) and not looks_like_totp(b):
        return b
    if looks_like_totp(b) and not looks_like_totp(a):
        return a

    if len(a) >= 60 and len(b) >= 10:
        return b
    if len(b) >= 60 and len(a) >= 10:
        return a

    if is_hex_len(a, 40) and is_hex_len(b, 32):
        return a
    if is_hex_len(b, 40) and is_hex_len(a, 32):
        return b

    if looks_like_token(a) and not looks_like_token(b):
        return a
    if looks_like_token(b) and not looks_like_token(a):
        return b

    return a if len(a) <= len(b) else b


def extract_auth_token(line: str) -> Optional[str]:
    match = AUTH_TOKEN_RE.search(line)
    if match:
        token = match.group(1).strip()
        return token or None

    parts = [part.strip() for part in line.split(":") if part.strip()]
    if not parts:
        return None

    if len(parts) == 1:
        return parts[0] if looks_like_token(parts[0]) else None

    if looks_like_totp(parts[-1]):
        parts = parts[:-1]
        if not parts:
            return None

    if len(parts) >= 2:
        a, b = parts[-2], parts[-1]
        token = pick_auth_from_pair(a, b)
        return token if looks_like_token(token) else None

    return None


def resolve_input(path_text: str) -> Path:
    path = Path(path_text)
    if path.is_file():
        return path
    fallback = Path(__file__).resolve().parent / path_text
    if fallback.is_file():
        return fallback
    raise FileNotFoundError(f"Input file not found: {path_text}")


def write_tokens(tokens: Iterable[str], output_path: Path) -> int:
    output_path.parent.mkdir(parents=True, exist_ok=True)
    with output_path.open("w", encoding="utf-8") as handle:
        count = 0
        for token in tokens:
            handle.write(token + "\n")
            count += 1
    return count


def main() -> None:
    parser = argparse.ArgumentParser(
        description="parse_auth_token.txt icinden auth_token degerlerini cikarir."
    )
    parser.add_argument(
        "input",
        nargs="?",
        default="parse_auth_token.txt",
        help="Girdi dosyasi (varsayilan: parse_auth_token.txt)",
    )
    parser.add_argument(
        "output",
        nargs="?",
        default=None,
        help="Cikti dosyasi (varsayilan: only_auth_token.txt, girdi ile ayni klasor)",
    )
    parser.add_argument(
        "--dedupe",
        action="store_true",
        help="Ayni auth_token degerlerini tekillestirir.",
    )
    args = parser.parse_args()

    input_path = resolve_input(args.input)
    output_path = Path(args.output) if args.output else input_path.with_name("only_auth_token.txt")

    raw_lines = input_path.read_text(encoding="utf-8-sig").splitlines()
    tokens = []
    seen = set()
    skipped = 0

    for raw_line in raw_lines:
        line = raw_line.strip()
        if not line:
            continue
        token = extract_auth_token(line)
        if not token:
            skipped += 1
            continue
        if args.dedupe:
            if token in seen:
                continue
            seen.add(token)
        tokens.append(token)

    written = write_tokens(tokens, output_path)

    print(f"Girdi: {input_path}")
    print(f"Satir: {len(raw_lines)} | Auth token: {written} | Atlanan: {skipped}")
    print(f"Cikti: {output_path}")


if __name__ == "__main__":
    main()
