import logging
import re
import select
import sys
from pathlib import Path
from typing import Optional

import configargparse
import curl_cffi
import llm
import pyperclip
from html2text import html2text

translate_prompt = "Translate the text (it can be in any language) into {to_language}. Don't explaint that the output is a translation. Tell me in case if you don't know about '{to_language}' language."


def translate(text: Optional[str] = None, file: Optional[str] = None, *, model: str, to_language: str, system_prompt: str):
    system_prompt = translate_prompt.format(to_language=to_language.capitalize())
    attachments = [llm.Attachment(path=file)] if file else []
    logging.debug(f"{text=}, {attachments=}, {model=}, {to_language=}, {system_prompt=}")
    response = llm.get_model(model).prompt(text, attachments=attachments, system=system_prompt)
    for chunk in response:
        print(chunk, end="")


def is_url(text: str) -> bool:
    return re.match(r"^https?://", text) is not None


def is_file(text: str) -> bool:
    return Path(text).exists()


def has_stdin_data() -> bool:
    return bool(select.select([sys.stdin], [], [], 0)[0])


def readability(url: str) -> str:
    return html2text(curl_cffi.get(url, impersonate="chrome").text)


def get_input_data(args) -> tuple[Optional[str], Optional[str]]:
    text = None
    file = None

    if args.text:
        text = " ".join(args.text)
    elif has_stdin_data():
        logging.warning("Using text from standard input.")
        text = sys.stdin.read()
    else:
        logging.warning("Using text from clipboard.")
        text = pyperclip.paste()

    text = text.strip()

    if not text:
        logging.error("Error: empty text! Please give me some text via stdin, command line arguments or in a clipboard.")
        sys.exit(1)

    if text:
        if is_url(text):
            text = readability(text)
        elif is_file(text):
            file = text
            text = None

    return text, file


def main():
    parser = configargparse.ArgumentParser(formatter_class=configargparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument("-t", "--to-language", env_var="TRN_TO_LANGUAGE", required=True, help="Target language for translation")
    parser.add_argument(
        "-m", "--model", env_var="TRN_MODEL", help="LLM to use (run 'uvx llm models' for available models)", default="gpt-4o-mini"
    )
    parser.add_argument("--prompt", env_var="TRN_PROMPT", help="Custom prompt for translation", default=translate_prompt)
    parser.add_argument("-v", "--verbose", env_var="TRN_VERBOSE", action="store_true", help="Enable verbose output")
    parser.add_argument("-d", "--debug", env_var="TRN_DEBUG", action="store_true", help="Enable debug output")
    parser.add_argument("text", nargs="*", help="Text to translate, or URL, or path to file")
    args = parser.parse_args()

    log_level = logging.ERROR
    if args.verbose:
        log_level = logging.WARNING
    if args.debug:
        log_level = logging.DEBUG
    logging.basicConfig(level=log_level, format="%(message)s")

    text, file = get_input_data(args)
    translate(text=text, file=file, model=args.model, to_language=args.to_language, system_prompt=args.prompt)


if __name__ == "__main__":
    main()
