/* eslint-disable @typescript-eslint/no-explicit-any */
import { html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { createRef, ref } from "lit/directives/ref.js";
import { SketchTailwindElement } from "./sketch-tailwind-element";

@customElement("mobile-chat-input")
export class MobileChatInput extends SketchTailwindElement {
  @property({ type: Boolean })
  disabled = false;

  @state()
  private inputValue = "";

  @state()
  private uploadsInProgress = 0;

  @state()
  private showUploadProgress = false;

  private textareaRef = createRef<HTMLTextAreaElement>();

  private handleInput = (e: Event) => {
    const target = e.target as HTMLTextAreaElement;
    this.inputValue = target.value;
    this.adjustTextareaHeight();
  };

  private handlePaste = async (e: ClipboardEvent) => {
    // Check if the clipboard contains files
    if (e.clipboardData && e.clipboardData.files.length > 0) {
      const file = e.clipboardData.files[0];

      // Handle the file upload
      e.preventDefault(); // Prevent default paste behavior

      // Get the current cursor position
      const textarea = this.textareaRef.value;
      const cursorPos = textarea
        ? textarea.selectionStart
        : this.inputValue.length;
      await this.uploadFile(file, cursorPos);
    }
  };

  // Utility function to handle file uploads
  private async uploadFile(file: File, insertPosition: number) {
    // Insert a placeholder at the cursor position
    const textBefore = this.inputValue.substring(0, insertPosition);
    const textAfter = this.inputValue.substring(insertPosition);

    // Add a loading indicator
    const loadingText = `[🔄 Uploading ${file.name}...]`;
    this.inputValue = `${textBefore}${loadingText}${textAfter}`;

    // Increment uploads in progress counter
    this.uploadsInProgress++;
    this.showUploadProgress = true;

    // Adjust spacing immediately to show loading indicator
    this.adjustTextareaHeight();

    try {
      // Create a FormData object to send the file
      const formData = new FormData();
      formData.append("file", file);

      // Upload the file to the server using a relative path
      const response = await fetch("./upload", {
        method: "POST",
        body: formData,
      });

      if (!response.ok) {
        throw new Error(`Upload failed: ${response.statusText}`);
      }

      const data = await response.json();

      // Replace the loading placeholder with the actual file path
      this.inputValue = this.inputValue.replace(loadingText, `[${data.path}]`);

      return data.path;
    } catch (error) {
      console.error("Failed to upload file:", error);

      // Replace loading indicator with error message
      const errorText = `[Upload failed: ${error.message}]`;
      this.inputValue = this.inputValue.replace(loadingText, errorText);

      throw error;
    } finally {
      // Always decrement the counter, even if there was an error
      this.uploadsInProgress--;
      if (this.uploadsInProgress === 0) {
        this.showUploadProgress = false;
      }
      this.adjustTextareaHeight();
      if (this.textareaRef.value) {
        this.textareaRef.value.focus();
      }
    }
  }

  private handleKeyDown = (e: KeyboardEvent) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      this.sendMessage();
    }
  };

  private adjustTextareaHeight() {
    if (this.textareaRef.value) {
      const textarea = this.textareaRef.value;
      textarea.style.height = "auto";
      textarea.style.height = Math.min(textarea.scrollHeight, 120) + "px";
    }
  }

  private sendMessage = () => {
    // Prevent sending if there are uploads in progress
    if (this.uploadsInProgress > 0) {
      console.log(
        `Message send prevented: ${this.uploadsInProgress} uploads in progress`,
      );
      return;
    }

    const message = this.inputValue.trim();
    if (message && !this.disabled) {
      this.dispatchEvent(
        new CustomEvent("send-message", {
          detail: { message },
          bubbles: true,
          composed: true,
        }),
      );

      this.inputValue = "";
      if (this.textareaRef.value) {
        this.textareaRef.value.value = "";
        this.adjustTextareaHeight();
        this.textareaRef.value.focus();
      }
    }
  };

  updated(changedProperties: Map<string, any>) {
    super.updated(changedProperties);
    this.adjustTextareaHeight();

    // Add paste event listener when component updates
    if (this.textareaRef.value && !this.textareaRef.value.onpaste) {
      this.textareaRef.value.addEventListener("paste", this.handlePaste);
    }
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    // Clean up paste event listener
    if (this.textareaRef.value) {
      this.textareaRef.value.removeEventListener("paste", this.handlePaste);
    }
  }

  render() {
    const canSend =
      this.inputValue.trim().length > 0 &&
      !this.disabled &&
      this.uploadsInProgress === 0;

    return html`
      <div
        class="block bg-white border-t border-gray-200 p-3 relative z-[1000]"
        style="padding-bottom: max(12px, env(safe-area-inset-bottom)); padding-left: max(16px, env(safe-area-inset-left)); padding-right: max(16px, env(safe-area-inset-right));"
      >
        <div class="flex items-end gap-3 max-w-full">
          <div class="flex-1 relative min-w-0">
            <textarea
              ${ref(this.textareaRef)}
              .value=${this.inputValue}
              @input=${this.handleInput}
              @keydown=${this.handleKeyDown}
              placeholder="Message Sketch..."
              ?disabled=${this.disabled || this.uploadsInProgress > 0}
              rows="1"
              class="w-full min-h-[40px] max-h-[120px] p-3 border border-gray-300 rounded-[20px] text-base font-inherit leading-relaxed resize-none outline-none bg-gray-50 transition-colors duration-200 box-border focus:border-blue-500 focus:bg-white disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-not-allowed placeholder:text-gray-500"
              style="font-size: 16px;"
            ></textarea>

            ${this.showUploadProgress
              ? html`
                  <div
                    class="absolute -top-8 left-1/2 transform -translate-x-1/2 bg-yellow-50 text-yellow-800 px-2 py-1 rounded text-xs whitespace-nowrap shadow-sm z-[1000]"
                  >
                    Uploading ${this.uploadsInProgress}
                    file${this.uploadsInProgress > 1 ? "s" : ""}...
                  </div>
                `
              : ""}
          </div>

          <button
            class="flex-shrink-0 w-10 h-10 border-none rounded-full bg-blue-500 text-white cursor-pointer flex items-center justify-center text-lg transition-all duration-200 outline-none hover:bg-blue-600 active:scale-95 disabled:bg-gray-500 disabled:cursor-not-allowed disabled:opacity-60"
            @click=${this.sendMessage}
            ?disabled=${!canSend}
            title=${this.uploadsInProgress > 0
              ? "Please wait for upload to complete"
              : "Send message"}
          >
            ${this.uploadsInProgress > 0
              ? html`<span class="text-xs">⏳</span>`
              : html`<svg class="w-4 h-4 fill-current" viewBox="0 0 24 24">
                  <path d="M2,21L23,12L2,3V10L17,12L2,14V21Z" />
                </svg>`}
          </button>
        </div>
      </div>
    `;
  }
}
