"""
Ferramentas do sistema
"""
import os
import time
import re
import csv
import random
import string
from datetime import datetime, timezone
from typing import Dict, Any, List


class SystemTools:
    """
    Ferramentas para informações do sistema e operações básicas
    """

    def __init__(self):
        self.start_time = time.time()

    def get_time(self, format_str: str = "%d/%m/%Y %H:%M:%S") -> str:
        """Retorna hora atual"""
        return datetime.now(timezone.utc).strftime(format_str)

    def get_date(self) -> str:
        """Retorna data atual"""
        return datetime.now(timezone.utc).strftime("%d/%m/%Y")

    def get_uptime(self) -> str:
        """Retorna tempo de atividade do sistema"""
        uptime_seconds = time.time() - self.start_time
        hours = int(uptime_seconds // 3600)
        minutes = int((uptime_seconds % 3600) // 60)
        seconds = int(uptime_seconds % 60)

        parts = []
        if hours > 0:
            parts.append(f"{hours}h")
        if minutes > 0:
            parts.append(f"{minutes}m")
        parts.append(f"{seconds}s")

        return " ".join(parts)

    def get_env(self, key: str) -> str:
        """Retorna variável de ambiente (versão segura)"""
        sensitive = ['SECRET', 'PASSWORD', 'TOKEN', 'KEY', 'API_KEY', 'PRIVATE']
        if any(s in key.upper() for s in sensitive):
            return "[PROTEGIDO]"
        return os.getenv(key, f"Variável {key} não encontrada")

    def echo(self, message: str) -> str:
        """Retorna a mensagem"""
        return message

    def calculate_age(self, birth_date: str) -> str:
        """Calcula idade a partir da data de nascimento"""
        try:
            birth = datetime.strptime(birth_date, "%d/%m/%Y")
            today = datetime.now()
            age = today.year - birth.year
            if (today.month, today.day) < (birth.month, birth.day):
                age -= 1
            return f"{age} anos"
        except ValueError:
            return "Formato inválido. Use DD/MM/YYYY"

    def format_currency(self, value: float, currency: str = "BRL") -> str:
        """Formata valor como moeda"""
        currencies = {
            "BRL": "R$",
            "USD": "$",
            "EUR": "€",
            "GBP": "£"
        }
        symbol = currencies.get(currency, currency)
        formatted = f"{value:,.2f}"
        return f"{symbol} {formatted}".replace(",", "X").replace(".", ",").replace("X", ".")

    def count_words(self, text: str) -> Dict[str, Any]:
        """Conta palavras no texto"""
        words = text.split()
        lines = text.split('\n')
        characters = len(text)

        return {
            "words": len(words),
            "lines": len(lines),
            "characters": characters,
            "characters_no_spaces": len(text.replace(" ", "").replace("\n", ""))
        }

    def generate_id(self, length: int = 8) -> str:
        """Gera ID aleatório"""
        return ''.join(random.choices(string.ascii_uppercase + string.digits, k=length))

    def validate_email(self, email: str) -> bool:
        """Valida formato de email"""
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        return bool(re.match(pattern, email))

    def truncate_text(self, text: str, max_length: int = 100, suffix: str = "...") -> str:
        """Trunca texto para tamanho máximo"""
        if len(text) <= max_length:
            return text
        return text[:max_length - len(suffix)] + suffix

    def slugify(self, text: str) -> str:
        """Converte texto para slug de URL"""
        text = text.lower()
        text = re.sub(r'[^\w\s-]', '', text)
        text = re.sub(r'[\s_-]+', '-', text)
        text = re.sub(r'^-+|-+$', '', text)
        return text

    def get_random_choice(self, options: List[str]) -> str:
        """Escolhe aleatoriamente da lista"""
        return random.choice(options)

    def format_list(self, items: List[str], separator: str = ", ", final_separator: str = " e ") -> str:
        """Formata lista com separadores"""
        if not items:
            return ""

        if len(items) == 1:
            return items[0]

        if len(items) == 2:
            return items[0] + final_separator + items[1]

        return separator.join(items[:-1]) + final_separator + items[-1]

    def parse_csv_line(self, line: str, delimiter: str = ",") -> List[str]:
        """Analisa linha CSV"""
        from io import StringIO
        reader = csv.reader(StringIO(line), delimiter=delimiter)
        return next(reader, [])

    def format_table(self, headers: List[str], rows: List[List[str]]) -> str:
        """Formata dados como tabela ASCII"""
        if not rows:
            return "Sem dados"

        col_widths = [len(h) for h in headers]
        for row in rows:
            for i, cell in enumerate(row):
                col_widths[i] = max(col_widths[i], len(str(cell)))

        lines = []
        header_cells = [headers[i].ljust(col_widths[i]) for i in range(len(headers))]
        lines.append(" | ".join(header_cells))
        lines.append("-" * (sum(col_widths) + 3 * (len(headers) - 1)))

        for row in rows:
            row_cells = [str(row[i]).ljust(col_widths[i]) for i in range(len(row))]
            lines.append(" | ".join(row_cells))

        return "\n".join(lines)

    def get_file_info(self, file_path: str) -> Dict[str, Any]:
        """Obtém informações do arquivo"""
        try:
            stat = os.stat(file_path)
            return {
                "exists": True,
                "size": stat.st_size,
                "modified": datetime.fromtimestamp(stat.st_mtime).isoformat(),
                "created": datetime.fromtimestamp(stat.st_ctime).isoformat(),
                "is_file": os.path.isfile(file_path),
                "is_dir": os.path.isdir(file_path),
            }
        except FileNotFoundError:
            return {"exists": False}

    def convert_temperature(self, value: float, from_unit: str, to_unit: str) -> float:
        """Converte temperatura entre Celsius, Fahrenheit e Kelvin"""
        from_unit = from_unit.upper()
        to_unit = to_unit.upper()

        # Converter para Celsius primeiro
        if from_unit == "C":
            celsius = value
        elif from_unit == "F":
            celsius = (value - 32) * 5 / 9
        elif from_unit == "K":
            celsius = value - 273.15
        else:
            raise ValueError(f"Unidade de origem inválida: {from_unit}")

        # Converter de Celsius para unidade destino
        if to_unit == "C":
            return celsius
        elif to_unit == "F":
            return (celsius * 9 / 5) + 32
        elif to_unit == "K":
            return celsius + 273.15
        else:
            raise ValueError(f"Unidade de destino inválida: {to_unit}")

    def generate_password(self, length: int = 12) -> str:
        """Gera senha segura"""
        chars = string.ascii_letters + string.digits + "!@#$%^&*"
        password = ''.join(random.choices(chars, k=length))
        return password

    def mask_cpf(self, cpf: str) -> str:
        """Mascara CPF"""
        digits = re.sub(r'\D', '', cpf)
        if len(digits) != 11:
            return "CPF inválido"
        return f"{digits[:3]}.***.***-{digits[-2:]}"

    def mask_phone(self, phone: str) -> str:
        """Mascara telefone"""
        digits = re.sub(r'\D', '', phone)
        if len(digits) < 10:
            return "Telefone inválido"
        return f"(***) ***-{digits[-4:]}"

    def days_between(self, date1: str, date2: str) -> int:
        """Calcula dias entre duas datas"""
        d1 = datetime.strptime(date1, "%d/%m/%Y")
        d2 = datetime.strptime(date2, "%d/%m/%Y")
        return abs((d2 - d1).days)

    def is_weekend(self, date_str: str = None) -> bool:
        """Verifica se é fim de semana"""
        if date_str:
            date = datetime.strptime(date_str, "%d/%m/%Y")
        else:
            date = datetime.now()
        return date.weekday() >= 5  # 5=Saturday, 6=Sunday