import { useState, useEffect, useRef } from "react";
import { ArrowLeftRight, Copy, Check, Share2, Trash } from "lucide-react";
import { Textarea, Button, Loader } from "./theme";
import cn from "./utils/classnames.ts";
import { type LanguageCode, LANGUAGES } from "./constants";
import LanguageSelector from "./components/LanguageSelector";
import Translator from "./ai/Translator.ts";
import { formatTime, formatNumber } from "./utils/format";
import { countWords } from "./utils/countWords.ts";

const MAX_INPUT_LENGTH = 1000;

interface TranslateProps {
  className?: string;
  translator: Translator;
}

export default function Translate({
  className = "",
  translator,
}: TranslateProps) {
  // Initialize from URL hash
  const getInitialState = () => {
    const hash = window.location.hash.slice(1); // Remove the # character
    const params = new URLSearchParams(hash);

    const sourceLang = params.get("sl");
    const targetLang = params.get("tl");
    const text = params.get("text");

    // Validate language codes
    const isValidLanguage = (code: string | null): code is LanguageCode => {
      if (!code) return false;
      return LANGUAGES.some((lang) => lang.code === code);
    };

    return {
      sourceLanguage: isValidLanguage(sourceLang)
        ? sourceLang
        : ("en" as LanguageCode),
      targetLanguage: isValidLanguage(targetLang)
        ? targetLang
        : ("de_DE" as LanguageCode),
      sourceText: text ? decodeURIComponent(text) : "",
    };
  };

  const initialState = getInitialState();

  const [sourceText, setSourceText] = useState(initialState.sourceText);
  const [targetText, setTargetText] = useState("");
  const [sourceLanguage, setSourceLanguage] = useState<LanguageCode>(
    initialState.sourceLanguage
  );
  const [targetLanguage, setTargetLanguage] = useState<LanguageCode>(
    initialState.targetLanguage
  );
  const [translating, setTranslating] = useState<boolean>(false);
  const [copied, setCopied] = useState<boolean>(false);
  const [shared, setShared] = useState<boolean>(false);
  const abortControllerRef = useRef<AbortController | null>(null);
  const [translationTime, setTranslationTime] = useState<number>(0);
  const [translationWords, setTranslationWords] = useState<number>(0);

  const handleSwapLanguages = () => {
    // Swap languages
    setSourceLanguage(targetLanguage);
    setTargetLanguage(sourceLanguage);

    // Swap text content
    setSourceText(targetText);
    setTargetText(sourceText);
  };

  const handleCopy = async () => {
    if (!targetText) return;

    try {
      await navigator.clipboard.writeText(targetText);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (error) {
      console.error("Failed to copy:", error);
    }
  };

  const handleShare = async () => {
    try {
      const currentUrl = window.location.href;
      await navigator.clipboard.writeText(currentUrl);
      setShared(true);
      setTimeout(() => setShared(false), 2000);
    } catch (error) {
      console.error("Failed to share:", error);
    }
  };

  const translate = async (
    text: string,
    sourceLang: LanguageCode,
    targetLang: LanguageCode
  ) => {
    if (!text.trim()) {
      setTargetText("");
      setTranslationTime(0);
      setTranslationWords(0);
      return;
    }

    const started = performance.now();

    if (abortControllerRef.current) {
      abortControllerRef.current.abort();
    }

    abortControllerRef.current = new AbortController();
    const currentController = abortControllerRef.current;

    setTranslating(true);

    try {
      const translation = await translator.translate(
        text,
        sourceLang,
        targetLang
      );

      if (!currentController.signal.aborted) {
        setTargetText(translation);
        setTranslationTime(Math.round(performance.now() - started));
        setTranslationWords(countWords(text));
      }
    } catch (error) {
      if (!currentController.signal.aborted) {
        console.error("Translation error:", error);
      }
    } finally {
      if (!currentController.signal.aborted) {
        setTranslating(false);
      }
    }
  };

  // Update URL hash when languages or text change
  useEffect(() => {
    const params = new URLSearchParams();
    params.set("sl", sourceLanguage);
    params.set("tl", targetLanguage);
    if (sourceText) {
      params.set("text", encodeURIComponent(sourceText));
    }

    window.location.hash = `#${params.toString()}`;
  }, [sourceLanguage, targetLanguage, sourceText]);

  useEffect(() => {
    const timer = setTimeout(() => {
      translate(sourceText, sourceLanguage, targetLanguage);
    }, 500);

    return () => {
      clearTimeout(timer);
    };
  }, [sourceText, sourceLanguage, targetLanguage]);

  return (
    <div className={cn("max-w-6xl mx-auto p-2 md:p-4 relative", className)}>
      <div className="flex flex-col md:flex-row w-full gap-4 md:gap-8">
        <div className="flex flex-col gap-3 w-full md:w-1/2 relative">
          <LanguageSelector
            value={sourceLanguage}
            onChange={setSourceLanguage}
          />
          <Textarea
            value={sourceText}
            onChange={(e) => setSourceText(e.target.value)}
            placeholder="Enter text to translate..."
            className="h-48 md:h-70 pb-10"
            variant="default"
            maxLength={MAX_INPUT_LENGTH}
          />
          <div className="p-2 flex justify-between items-center -mt-4">
            <p className="text-xs text-muted-foreground opacity-70">
              {formatNumber(sourceText.length)} /{" "}
              {formatNumber(MAX_INPUT_LENGTH)}
            </p>
            <div className="flex gap-2">
              <button
                onClick={handleShare}
                className="p-2 text-muted-foreground hover:text-primary hover:bg-muted rounded-md transition-colors"
                aria-label="Share translation"
              >
                {shared ? (
                  <span className="flex text-xs gap-2">
                    link copied
                    <Check className="w-4 h-4 text-primary" />
                  </span>
                ) : (
                  <Share2 className="w-4 h-4" />
                )}
              </button>
              <button
                onClick={() => setSourceText("")}
                className="p-2 text-muted-foreground hover:text-primary hover:bg-muted rounded-md transition-colors"
                aria-label="clear text"
              >
                <Trash className="w-4 h-4" />
              </button>
            </div>
          </div>
        </div>

        <div className="hidden md:block absolute left-1/2 top-5 -translate-x-1/2">
          <Button
            variant="ghost"
            icon={ArrowLeftRight}
            onClick={handleSwapLanguages}
            aria-label="Swap languages"
          />
        </div>

        <div className="flex md:hidden justify-center -my-2">
          <Button
            variant="ghost"
            icon={ArrowLeftRight}
            onClick={handleSwapLanguages}
            aria-label="Swap languages"
            className="rotate-90"
          />
        </div>

        <div className="flex flex-col gap-3 w-full md:w-1/2">
          <div className="flex items-center justify-between">
            <LanguageSelector
              value={targetLanguage}
              onChange={setTargetLanguage}
            />
            {translating && <Loader size={20} />}
          </div>
          <div>
            <Textarea
              value={targetText}
              disabled
              placeholder="Translation will appear here..."
              className="h-48 md:h-70"
              variant="default"
            />
            <div className="p-2 flex justify-between items-center -mt-4">
              {translationTime > 0 ? (
                <p className="text-xs text-muted-foreground opacity-70">
                  Translated <b>{formatNumber(translationWords)} words</b> in{" "}
                  <b>{formatTime(translationTime)}</b>
                </p>
              ) : (
                <p />
              )}
              <div>
                <button
                  onClick={handleCopy}
                  className="p-2 text-muted-foreground hover:text-primary hover:bg-muted rounded-md transition-colors"
                  aria-label="Copy translation"
                >
                  {copied ? (
                    <span className="flex text-xs gap-2">
                      translation copied
                      <Check className="w-4 h-4 text-primary" />
                    </span>
                  ) : (
                    <Copy className="w-4 h-4" />
                  )}
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}
