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

import { css, html, LitElement } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { GitDataService, DefaultGitDataService } from "./git-data-service";
import { GitLogEntry } from "../types";

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

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

  @state()
  private rangeType: "range" | "single" = "range";

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

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

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

  @state()
  private loading: boolean = true;

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

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

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

  static styles = css`
    :host {
      display: block;
      width: 100%;
      font-family: var(--font-family, system-ui, sans-serif);
      color: var(--text-color, #333);
    }

    .range-picker {
      display: flex;
      flex-direction: row;
      align-items: center;
      gap: 12px;
      padding: 12px;
      background-color: var(--background-light, #f8f8f8);
      border-radius: 4px;
      border: 1px solid var(--border-color, #e0e0e0);
      flex-wrap: wrap; /* Allow wrapping on small screens */
      width: 100%;
      box-sizing: border-box;
    }

    .range-type-selector {
      display: flex;
      gap: 16px;
      flex-shrink: 0;
    }

    .range-type-option {
      display: flex;
      align-items: center;
      gap: 6px;
      cursor: pointer;
      white-space: nowrap;
    }

    .commit-selectors {
      display: flex;
      flex-direction: row;
      align-items: center;
      gap: 12px;
      flex: 1;
      flex-wrap: wrap; /* Allow wrapping on small screens */
    }

    .commit-selector {
      display: flex;
      align-items: center;
      gap: 8px;
      flex: 1;
      min-width: 200px;
      max-width: calc(50% - 12px); /* Half width minus half the gap */
      overflow: hidden;
    }

    select {
      padding: 6px 8px;
      border-radius: 4px;
      border: 1px solid var(--border-color, #e0e0e0);
      background-color: var(--background, #fff);
      max-width: 100%;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }

    label {
      font-weight: 500;
      font-size: 14px;
    }

    .loading {
      font-style: italic;
      color: var(--text-muted, #666);
    }

    .error {
      color: var(--error-color, #dc3545);
      font-size: 14px;
    }

    .refresh-button {
      padding: 6px 12px;
      background-color: #f0f0f0;
      color: var(--text-color, #333);
      border: 1px solid var(--border-color, #e0e0e0);
      border-radius: 4px;
      cursor: pointer;
      font-size: 14px;
      transition: background-color 0.2s;
      white-space: nowrap;
      display: flex;
      align-items: center;
      gap: 4px;
    }

    .refresh-button:hover {
      background-color: #e0e0e0;
    }

    .refresh-button:disabled {
      background-color: #f8f8f8;
      color: #999;
      cursor: not-allowed;
    }

    @media (max-width: 768px) {
      .commit-selector {
        max-width: 100%;
      }
    }
  `;

  connectedCallback() {
    super.connectedCallback();
    // 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="range-picker">
        ${this.loading
          ? html`<div class="loading">Loading commits...</div>`
          : this.error
            ? html`<div class="error">${this.error}</div>`
            : this.renderRangePicker()}
      </div>
    `;
  }

  renderRangePicker() {
    return html`
      <div class="range-type-selector">
        <label class="range-type-option">
          <input
            type="radio"
            name="rangeType"
            value="range"
            ?checked=${this.rangeType === "range"}
            @change=${() => this.setRangeType("range")}
          />
          Commit Range
        </label>
        <label class="range-type-option">
          <input
            type="radio"
            name="rangeType"
            value="single"
            ?checked=${this.rangeType === "single"}
            @change=${() => this.setRangeType("single")}
          />
          Single Commit
        </label>
      </div>

      <div class="commit-selectors">
        ${this.rangeType === "range"
          ? this.renderRangeSelectors()
          : this.renderSingleSelector()}
      </div>

      <button
        class="refresh-button"
        @click="${this.handleRefresh}"
        ?disabled="${this.loading}"
        title="Refresh commit list"
      >
        🔄 Refresh
      </button>
    `;
  }

  renderRangeSelectors() {
    return html`
      <div class="commit-selector">
        <label for="fromCommit">From:</label>
        <select
          id="fromCommit"
          .value=${this.fromCommit}
          @change=${this.handleFromChange}
        >
          ${this.commits.map(
            (commit) => html`
              <option
                value=${commit.hash}
                ?selected=${commit.hash === this.fromCommit}
              >
                ${this.formatCommitOption(commit)}
              </option>
            `,
          )}
        </select>
      </div>
      <div class="commit-selector">
        <label for="toCommit">To:</label>
        <select
          id="toCommit"
          .value=${this.toCommit}
          @change=${this.handleToChange}
        >
          <option value="" ?selected=${this.toCommit === ""}>
            Uncommitted Changes
          </option>
          ${this.commits.map(
            (commit) => html`
              <option
                value=${commit.hash}
                ?selected=${commit.hash === this.toCommit}
              >
                ${this.formatCommitOption(commit)}
              </option>
            `,
          )}
        </select>
      </div>
    `;
  }

  renderSingleSelector() {
    return html`
      <div class="commit-selector">
        <label for="singleCommit">Commit:</label>
        <select
          id="singleCommit"
          .value=${this.singleCommit}
          @change=${this.handleSingleChange}
        >
          ${this.commits.map(
            (commit) => html`
              <option
                value=${commit.hash}
                ?selected=${commit.hash === this.singleCommit}
              >
                ${this.formatCommitOption(commit)}
              </option>
            `,
          )}
        </select>
      </div>
    `;
  }

  /**
   * Format a commit for display in the dropdown
   */
  formatCommitOption(commit: GitLogEntry): string {
    const shortHash = commit.hash.substring(0, 7);
    let label = `${shortHash} ${commit.subject}`;

    if (commit.refs && commit.refs.length > 0) {
      label += ` (${commit.refs.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

        // For single, default to HEAD
        this.singleCommit = this.commits[0].hash;
      }

      // 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 range type change
   */
  setRangeType(type: "range" | "single") {
    this.rangeType = type;

    // If switching to range mode and we don't have valid commits set,
    // initialize with sensible defaults
    if (
      type === "range" &&
      (!this.fromCommit || !this.toCommit === undefined)
    ) {
      if (this.commits.length > 0) {
        const baseCommit = this.commits.find(
          (c) => c.refs && c.refs.some((ref) => ref.includes("sketch-base")),
        );
        if (!this.fromCommit) {
          this.fromCommit = baseCommit
            ? baseCommit.hash
            : this.commits[this.commits.length - 1].hash;
        }
        if (this.toCommit === undefined) {
          this.toCommit = ""; // Default to uncommitted changes
        }
      }
    }

    // If switching to single mode and we don't have a valid commit set,
    // initialize with HEAD
    if (type === "single" && !this.singleCommit && this.commits.length > 0) {
      this.singleCommit = this.commits[0].hash;
    }

    this.dispatchRangeEvent();
  }

  /**
   * 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();
  }

  /**
   * Handle Single commit change
   */
  handleSingleChange(event: Event) {
    const select = event.target as HTMLSelectElement;
    this.singleCommit = select.value;
    this.dispatchRangeEvent();
  }

  /**
   * Handle refresh button click
   */
  handleRefresh() {
    this.loadCommits();
  }

  /**
   * 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 =
      this.rangeType === "range"
        ? { type: "range", from: this.fromCommit, to: this.toCommit }
        : { type: "single", commit: this.singleCommit };

    // 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");

    if (range.type === "range") {
      // 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);
      }
    } else {
      // Single commit mode
      if (range.commit && range.commit.trim() !== "") {
        url.searchParams.set("commit", range.commit);
      }
    }

    // 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");
    const commitParam = url.searchParams.get("commit");

    // If commit parameter is present, switch to single commit mode
    if (commitParam) {
      this.rangeType = "single";
      this.singleCommit = commitParam;
      return true; // Indicate that we initialized from URL
    }

    // If from or to parameters are present, use range mode
    if (fromParam || toParam) {
      this.rangeType = "range";
      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;
  }
}
