# -*- coding: utf-8 -*-
"""
Text utilities for LVT4U plugin.
Author: Lộc Vũ Trung / Slow Forest
License: GPL-3.0
"""
from __future__ import annotations
import os
import re
import unicodedata


def clean_ogr_text(s) -> str:
    """
    Sanitize text returned by OGR/GDAL to be safely writable to QgsVectorLayer.

    OGR sometimes returns strings with PEP-383 surrogate-escape sequences
    (e.g. \\udcab) when reading DGN/DXF files containing TCVN3-encoded text.
    Writing such strings directly to a feature attribute causes:
        UnicodeEncodeError: 'utf-8' codec can't encode: surrogates not allowed

    Strategy:
        1. Try to encode as UTF-8 — if OK, return as-is.
        2. On failure, encode with surrogate-escape then decode as cp1252
           (the common byte range for TCVN3 characters is cp1252-compatible).
    """
    if s is None:
        return ''
    if not isinstance(s, str):
        return str(s)
    try:
        s.encode('utf-8')
        return s
    except (UnicodeEncodeError, UnicodeDecodeError):
        try:
            return s.encode('utf-8', 'surrogateescape').decode('cp1252', 'replace')
        except Exception:
            return s.encode('ascii', 'replace').decode('ascii')


def remove_accents(text: str) -> str:
    """
    Remove Vietnamese diacritics for accent-insensitive comparison.
    Uses NFD normalization: decomposes each accented char into base + combining
    marks, then strips the combining marks (Unicode category 'Mn').
    Handles đ/Đ specially (no combining mark equivalent).
    """
    nfd = unicodedata.normalize('NFD', text)
    result = ''.join(c for c in nfd if unicodedata.category(c) != 'Mn')
    # đ/Đ have no NFD decomposition — replace manually
    return result.replace('đ', 'd').replace('Đ', 'D')


def sanitize_filename(name: str, max_len: int = 50) -> str:
    """
    Convert a CAD layer/level name into a safe filesystem filename.
    Removes or replaces characters not allowed in Windows filenames.
    """
    if not name:
        return 'unnamed'
    # Remove accents for cross-platform safety
    safe = remove_accents(name)
    # Replace forbidden characters with underscore
    safe = re.sub(r'[\\/:*?"<>|\s]+', '_', safe)
    # Remove leading/trailing underscores and dots
    safe = safe.strip('_.')
    # Truncate
    if len(safe) > max_len:
        safe = safe[:max_len].rstrip('_')
    return safe or 'L'


def truncate_field_name(name: str, max_len: int = 10) -> str:
    """
    Truncate a field name to fit ESRI Shapefile's 10-character limit.
    Strips accents first to avoid multi-byte issues.
    """
    safe = remove_accents(name)
    safe = re.sub(r'[^A-Za-z0-9_]', '_', safe)
    return safe[:max_len]


def get_unique_path(path: str) -> str:
    """
    If `path` already exists, append _1, _2, ... until a unique path is found.
    Works for both files and directories.
    """
    if not os.path.exists(path):
        return path
    base, ext = os.path.splitext(path)
    counter = 1
    while True:
        candidate = f'{base}_{counter}{ext}'
        if not os.path.exists(candidate):
            return candidate
        counter += 1
