// sketch-diff-range-picker.ts
// Component for selecting commit range for diffs

import { html } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { GitDataService } from "./git-data-service";
import { GitLogEntry } from "../types";
import { SketchTailwindElement } from "./sketch-tailwind-element";

/**
 * Range type for diff views
 */
export type DiffRange = { type: "range"; from: string; to: string };

/**
 * Component for selecting commit range for diffs
 */
@customElement("sketch-diff-range-picker")
export class SketchDiffRangePicker extends SketchTailwindElement {
  @property({ type: Array })
  commits: GitLogEntry[] = [];

  @state()
  private fromCommit: string = "";

  @state()
  private toCommit: string = "";

  @state()
  private dropdownOpen: boolean = false;

  // Removed commitsExpanded state - always expanded now

  @state()
  private loading: boolean = true;

  @state()
  private error: string | null = null;

  @property({ attribute: false, type: Object })
  gitService!: GitDataService;

  constructor() {
    super();
    console.log("SketchDiffRangePicker initialized");
  }

  // Ensure global styles are injected when component is used
  private ensureGlobalStyles() {
    if (!document.querySelector("#sketch-diff-range-picker-styles")) {
      const floatingMessageStyles = document.createElement("style");
      floatingMessageStyles.id = "sketch-diff-range-picker-styles";
      floatingMessageStyles.textContent = this.getGlobalStylesContent();
      document.head.appendChild(floatingMessageStyles);
    }
  }

  // Get the global styles content
  private getGlobalStylesContent(): string {
    return `
    sketch-diff-range-picker {
      display: block;
      width: 100%;
      font-family: var(--font-family, system-ui, sans-serif);
      color: var(--text-color, #333);
    }`;
  }

  connectedCallback() {
    super.connectedCallback();
    this.ensureGlobalStyles();
    // Wait for DOM to be fully loaded to ensure proper initialization order
    if (document.readyState === "complete") {
      this.loadCommits();
    } else {
      window.addEventListener("load", () => {
        setTimeout(() => this.loadCommits(), 0); // Give time for provider initialization
      });
    }

    // Listen for popstate events to handle browser back/forward navigation
    window.addEventListener("popstate", this.handlePopState.bind(this));
  }

  disconnectedCallback() {
    super.disconnectedCallback();
    window.removeEventListener("popstate", this.handlePopState.bind(this));
  }

  /**
   * Handle browser back/forward navigation
   */
  private handlePopState() {
    // Re-initialize from URL parameters when user navigates
    if (this.commits.length > 0) {
      const initializedFromUrl = this.initializeFromUrlParams();
      if (initializedFromUrl) {
        // Force re-render and dispatch event
        this.requestUpdate();
        this.dispatchRangeEvent();
      }
    }
  }

  render() {
    return html`
      <div class="block w-full font-system text-gray-800 dark:text-gray-200">
        <div class="flex flex-col gap-3 w-full">
          ${this.loading
            ? html`<div class="italic text-gray-500 dark:text-gray-400">
                Loading commits...
              </div>`
            : this.error
              ? html`<div class="text-red-600 dark:text-red-400 text-sm">
                  ${this.error}
                </div>`
              : this.renderRangePicker()}
        </div>
      </div>
    `;
  }

  renderRangePicker() {
    return html`
      <div class="flex flex-row items-center gap-3 flex-1">
        ${this.renderRangeSelectors()}
      </div>
    `;
  }

  renderRangeSelectors() {
    // Always diff against uncommitted changes
    this.toCommit = "";

    const selectedCommit = this.commits.find((c) => c.hash === this.fromCommit);
    const isDefaultCommit =
      selectedCommit && this.isSketchBaseCommit(selectedCommit);

    return html`
      <div class="flex items-center gap-2 flex-1 relative">
        <label
          for="fromCommit"
          class="font-medium text-sm text-gray-700 dark:text-gray-300"
          >Diff from:</label
        >
        <div
          class="relative w-full min-w-[300px]"
          @click=${this.toggleDropdown}
        >
          <button
            class="w-full py-2 px-3 pr-8 border rounded text-left min-h-[36px] text-sm relative cursor-pointer bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 ${isDefaultCommit
              ? "border-blue-500 bg-blue-50 dark:bg-blue-900/30"
              : "border-gray-300 dark:border-gray-600 hover:border-gray-400 dark:hover:border-gray-500"} focus:outline-none focus:border-blue-500 focus:ring-2 focus:ring-blue-200 dark:focus:ring-blue-800"
            @click=${this.toggleDropdown}
            @blur=${this.handleBlur}
          >
            <div class="flex items-center gap-2 pr-6">
              ${selectedCommit
                ? this.renderCommitButton(selectedCommit)
                : "Select commit..."}
            </div>
            <svg
              class="absolute right-2 top-1/2 transform -translate-y-1/2 transition-transform duration-200 ${this
                .dropdownOpen
                ? "rotate-180"
                : ""}"
              width="12"
              height="12"
              viewBox="0 0 12 12"
            >
              <path d="M6 8l-4-4h8z" fill="currentColor" />
            </svg>
          </button>
          ${this.dropdownOpen
            ? html`
                <div
                  class="absolute top-full left-0 right-0 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded shadow-lg z-50 max-h-[300px] overflow-y-auto mt-0.5"
                >
                  ${this.commits.map(
                    (commit) => html`
                      <div
                        class="px-3 py-2.5 cursor-pointer border-b border-gray-100 dark:border-gray-700 last:border-b-0 flex items-start gap-2 text-sm leading-5 hover:bg-gray-50 dark:hover:bg-gray-700 ${commit.hash ===
                        this.fromCommit
                          ? "bg-blue-50 dark:bg-blue-900/30"
                          : ""} ${this.isSketchBaseCommit(commit)
                          ? "bg-blue-50 dark:bg-blue-900/30 border-l-4 border-l-blue-500 pl-2"
                          : ""}"
                        @click=${() => this.selectCommit(commit.hash)}
                      >
                        ${this.renderCommitOption(commit)}
                      </div>
                    `,
                  )}
                </div>
              `
            : ""}
        </div>
      </div>
    `;
  }

  /**
   * Format a commit for display in the dropdown (legacy method, kept for compatibility)
   */
  formatCommitOption(commit: GitLogEntry): string {
    const shortHash = commit.hash.substring(0, 7);

    // Truncate subject if it's too long
    let subject = commit.subject;
    if (subject.length > 50) {
      subject = subject.substring(0, 47) + "...";
    }

    let label = `${shortHash} ${subject}`;

    // Add refs but keep them concise
    if (commit.refs && commit.refs.length > 0) {
      const refs = commit.refs.map((ref) => {
        // Shorten common prefixes
        if (ref.startsWith("origin/")) {
          return ref.substring(7);
        }
        if (ref.startsWith("refs/heads/")) {
          return ref.substring(11);
        }
        if (ref.startsWith("refs/remotes/origin/")) {
          return ref.substring(20);
        }
        return ref;
      });

      // Limit to first 2 refs to avoid overcrowding
      const displayRefs = refs.slice(0, 2);
      if (refs.length > 2) {
        displayRefs.push(`+${refs.length - 2} more`);
      }

      label += ` (${displayRefs.join(", ")})`;
    }

    return label;
  }

  /**
   * Load commits from the Git data service
   */
  async loadCommits() {
    this.loading = true;
    this.error = null;

    if (!this.gitService) {
      console.error("GitService was not provided to sketch-diff-range-picker");
      throw Error();
    }

    try {
      // Get the base commit reference
      const baseCommitRef = await this.gitService.getBaseCommitRef();

      // Load commit history
      this.commits = await this.gitService.getCommitHistory(baseCommitRef);

      // Check if we should initialize from URL parameters first
      const initializedFromUrl = this.initializeFromUrlParams();

      // Set default selections only if not initialized from URL
      if (this.commits.length > 0 && !initializedFromUrl) {
        // For range, default is base to HEAD
        // TODO: is sketch-base right in the unsafe context, where it's sketch-base-...
        // should this be startswith?
        const baseCommit = this.commits.find(
          (c) => c.refs && c.refs.some((ref) => ref.includes("sketch-base")),
        );

        this.fromCommit = baseCommit
          ? baseCommit.hash
          : this.commits[this.commits.length - 1].hash;
        // Default to Uncommitted Changes by setting toCommit to empty string
        this.toCommit = ""; // Empty string represents uncommitted changes
      }

      // Always dispatch range event to ensure diff view is updated
      this.dispatchRangeEvent();
    } catch (error) {
      console.error("Error loading commits:", error);
      this.error = `Error loading commits: ${error.message}`;
    } finally {
      this.loading = false;
    }
  }

  /**
   * Handle From commit change
   */
  handleFromChange(event: Event) {
    const select = event.target as HTMLSelectElement;
    this.fromCommit = select.value;
    this.dispatchRangeEvent();
  }

  /**
   * Handle To commit change
   */
  handleToChange(event: Event) {
    const select = event.target as HTMLSelectElement;
    this.toCommit = select.value;
    this.dispatchRangeEvent();
  }

  /**
   * Toggle dropdown open/closed
   */
  toggleDropdown(event: Event) {
    event.stopPropagation();
    this.dropdownOpen = !this.dropdownOpen;

    if (this.dropdownOpen) {
      // Close dropdown when clicking outside
      setTimeout(() => {
        document.addEventListener("click", this.closeDropdown, { once: true });
      }, 0);
    }
  }

  /**
   * Close dropdown
   */
  closeDropdown = () => {
    this.dropdownOpen = false;
  };

  /**
   * Handle blur event on select button
   */
  handleBlur(_event: FocusEvent) {
    // Small delay to allow click events to process
    setTimeout(() => {
      if (!this.closest(".custom-select")) {
        this.dropdownOpen = false;
      }
    }, 150);
  }

  /**
   * Select a commit from dropdown
   */
  selectCommit(hash: string) {
    this.fromCommit = hash;
    this.dropdownOpen = false;
    this.dispatchRangeEvent();
  }

  /**
   * Check if a commit is a sketch-base commit
   */
  isSketchBaseCommit(commit: GitLogEntry): boolean {
    return commit.refs?.some((ref) => ref.includes("sketch-base")) || false;
  }

  /**
   * Render commit for the dropdown button
   */
  renderCommitButton(commit: GitLogEntry) {
    const shortHash = commit.hash.substring(0, 7);
    let subject = commit.subject;
    if (subject.length > 40) {
      subject = subject.substring(0, 37) + "...";
    }

    return html`
      <span class="font-mono text-gray-600 dark:text-gray-400 text-xs"
        >${shortHash}</span
      >
      <span class="text-gray-800 dark:text-gray-200 text-xs truncate"
        >${subject}</span
      >
      ${this.isSketchBaseCommit(commit)
        ? html`
            <span
              class="bg-blue-600 text-white px-1.5 py-0.5 rounded-full text-xs font-semibold"
              >base</span
            >
          `
        : ""}
    `;
  }

  /**
   * Render commit option in dropdown
   */
  renderCommitOption(commit: GitLogEntry) {
    const shortHash = commit.hash.substring(0, 7);
    let subject = commit.subject;
    if (subject.length > 50) {
      subject = subject.substring(0, 47) + "...";
    }

    return html`
      <span class="font-mono text-gray-600 dark:text-gray-400 text-xs"
        >${shortHash}</span
      >
      <span
        class="text-gray-800 dark:text-gray-200 text-xs flex-1 truncate min-w-[200px]"
        >${subject}</span
      >
      ${commit.refs && commit.refs.length > 0
        ? html`
            <div class="flex gap-1 flex-wrap">
              ${this.renderRefs(commit.refs)}
            </div>
          `
        : ""}
    `;
  }

  /**
   * Render all refs naturally without truncation
   */
  renderRefs(refs: string[]) {
    return html`
      <div class="flex gap-1 flex-wrap flex-shrink-0">
        ${refs.map((ref) => {
          const shortRef = this.getShortRefName(ref);
          const isSketchBase = ref.includes("sketch-base");
          const refClass = isSketchBase
            ? "bg-blue-600 text-white font-semibold"
            : ref.includes("tag")
              ? "bg-amber-100 dark:bg-amber-900 text-amber-800 dark:text-amber-200"
              : "bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200";
          return html`<span
            class="px-1.5 py-0.5 rounded-full text-xs font-medium ${refClass}"
            >${shortRef}</span
          >`;
        })}
      </div>
    `;
  }

  /**
   * Get shortened reference name for compact display
   */
  getShortRefName(ref: string): string {
    if (ref.startsWith("refs/heads/")) {
      return ref.substring(11);
    }
    if (ref.startsWith("refs/remotes/origin/")) {
      return ref.substring(20);
    }
    if (ref.startsWith("refs/tags/")) {
      return ref.substring(10);
    }
    return ref;
  }

  /**
   * Get a summary of the current commit range for display
   */
  getCommitSummary(): string {
    if (!this.fromCommit && !this.toCommit) {
      return "No commits selected";
    }

    const fromShort = this.fromCommit ? this.fromCommit.substring(0, 7) : "";
    const toShort = this.toCommit
      ? this.toCommit.substring(0, 7)
      : "Uncommitted";

    return `${fromShort}..${toShort}`;
  }

  /**
   * Validate that a commit hash exists in the loaded commits
   */
  private isValidCommitHash(hash: string): boolean {
    if (!hash || hash.trim() === "") return true; // Empty is valid (uncommitted changes)
    return this.commits.some(
      (commit) => commit.hash.startsWith(hash) || commit.hash === hash,
    );
  }

  /**
   * Dispatch range change event and update URL parameters
   */
  dispatchRangeEvent() {
    const range: DiffRange = {
      type: "range",
      from: this.fromCommit,
      to: this.toCommit,
    };

    // Update URL parameters
    this.updateUrlParams(range);

    const event = new CustomEvent("range-change", {
      detail: { range },
      bubbles: true,
      composed: true,
    });

    this.dispatchEvent(event);
  }

  /**
   * Update URL parameters for from and to commits
   */
  private updateUrlParams(range: DiffRange) {
    const url = new URL(window.location.href);

    // Remove existing range parameters
    url.searchParams.delete("from");
    url.searchParams.delete("to");
    url.searchParams.delete("commit");

    // Add from parameter if not empty
    if (range.from && range.from.trim() !== "") {
      url.searchParams.set("from", range.from);
    }
    // Add to parameter if not empty (empty string means uncommitted changes)
    if (range.to && range.to.trim() !== "") {
      url.searchParams.set("to", range.to);
    }

    // Update the browser history without reloading the page
    window.history.replaceState(window.history.state, "", url.toString());
  }

  /**
   * Initialize from URL parameters if available
   */
  private initializeFromUrlParams() {
    const url = new URL(window.location.href);
    const fromParam = url.searchParams.get("from");
    const toParam = url.searchParams.get("to");

    // If from or to parameters are present, use them
    if (fromParam || toParam) {
      if (fromParam) {
        this.fromCommit = fromParam;
      }
      if (toParam) {
        this.toCommit = toParam;
      } else {
        // If no 'to' param, default to uncommitted changes (empty string)
        this.toCommit = "";
      }
      return true; // Indicate that we initialized from URL
    }

    return false; // No URL params found
  }
}

declare global {
  interface HTMLElementTagNameMap {
    "sketch-diff-range-picker": SketchDiffRangePicker;
  }
}
