import { LitElement, html, css } from 'lit';
import { customElement, state } from 'lit/decorators.js';
import { when } from 'lit/directives/when.js';
import { listIssueDuplicates, checkAIVerdict } from '../api';
import type { DuplicatePair } from '../types';
import { AIModelVerdict, renderVerdict } from '../utils/verdict';
import '@shoelace-style/shoelace/dist/components/card/card.js';
import '@shoelace-style/shoelace/dist/components/button/button.js';
import '@shoelace-style/shoelace/dist/components/badge/badge.js';

@customElement('similar-issues-widget')
export class SimilarIssuesWidget extends LitElement {
  @state() private _topSuggestions: DuplicatePair[] = [];
  @state() private _totalSuggestions = 0;
  @state() private _loading = true;
  @state() private _error: string | null = null;
  @state() private _aiVerdicts: Record<string, AIModelVerdict> = {};

  static styles = css`
    :host {
      display: flex; /* Use flexbox to control child layout */
    }
    ::part(body) {
      padding: 0;
    }
    a {
      color: var(--sl-color-primary-600);
      text-decoration: none;
    }
    a:hover {
      text-decoration: underline;
    }
    sl-alert::part(base),
    sl-card {
      width: 100%;
    }
    sl-card::part(header) {
      background-color: var(--sl-color-neutral-100);
    }
    .suggestion-list {
      list-style: none;
      padding: 0;
      margin: 0;
    }
    .suggestion-item {
      display: flex;
      justify-content: space-between;
      align-items: center;
      padding: var(--sl-spacing-x-small) var(--sl-spacing-large);
      border-top: 1px solid var(--sl-color-neutral-200);
    }
    .sub-header {
      font-size: var(--sl-font-size-small);
      padding: var(--sl-spacing-small) var(--sl-spacing-large);
      padding-top: var(--sl-spacing-large);
    }
    .suggestion-item:last-child {
      border-bottom: 1px solid var(--sl-color-neutral-200);
    }
    .issue-titles {
      font-size: var(--sl-font-size-small);
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .verdict-container {
      margin-left: var(--sl-spacing-medium);
      display: inline-flex;
      align-items: center;
    }
    .see-all-container {
      text-align: center;
      padding: var(--sl-spacing-medium);
    }
    .spinner-container {
      display: flex;
      justify-content: center;
      padding: var(--sl-spacing-large);
    }
  `;

  async connectedCallback() {
    super.connectedCallback();
    this.fetchTopSuggestions();
  }

  async fetchTopSuggestions() {
    this._loading = true;
    try {
      const response = await listIssueDuplicates({ limit: 101 }); // Fetch 101 to check for >100
      const allPairs = response.duplicates;

      allPairs.sort((a, b) => b.similarity - a.similarity);

      this._topSuggestions = allPairs.slice(0, 3);
      this._totalSuggestions = allPairs.length;
      this._error = null;
      await this.fetchAIModelVerdicts();
    } catch (error) {
      console.error('Failed to fetch similar issues:', error);
      this._error = 'Could not load suggestions.';
    } finally {
      this._loading = false;
    }
  }

  async fetchAIModelVerdicts() {
    // 1. Set all to 'checking' and update the UI once.
    const initialVerdicts: Record<string, AIModelVerdict> = {};
    const pairsToFetch: DuplicatePair[] = [];

    for (const pair of this._topSuggestions) {
      if (pair.similarity < 0.999) {
        const pairKey = `${pair.issue1.id}-${pair.issue2.id}`;
        initialVerdicts[pairKey] = { decision: 'checking' };
        pairsToFetch.push(pair);
      }
    }
    this._aiVerdicts = initialVerdicts;

    // 2. Create an array of promises for all the API calls.
    const verdictPromises = pairsToFetch.map((pair) =>
      checkAIVerdict(pair.issue1.id, pair.issue2.id).catch((error) => {
        console.error(
          `[similar-issues-widget] fetchAIModelVerdicts: API call failed for pair ${pair.issue1.id}-${pair.issue2.id}`,
          error
        );
        // Return a specific error object so Promise.all doesn't fail completely
        return { error: true, pairKey: `${pair.issue1.id}-${pair.issue2.id}` };
      })
    );

    if (verdictPromises.length === 0) {
      return;
    }

    // 3. Wait for all promises to settle.
    const results = await Promise.all(verdictPromises);

    // 4. Process the results and update the state a final time.
    const finalVerdicts = { ...this._aiVerdicts };
    results.forEach((result, index) => {
      const pair = pairsToFetch[index];
      const pairKey = `${pair.issue1.id}-${pair.issue2.id}`;

      if (result.error) {
        finalVerdicts[pairKey] = {
          decision: 'undecided',
          reason: 'Failed to load',
        };
      } else {
        finalVerdicts[pairKey] = {
          decision: result.decision || 'undecided',
          reason: result.reason,
        };
      }
    });

    this._aiVerdicts = finalVerdicts;
  }

  render() {
    if (this._loading) {
      return html`
        <sl-card class="table-card">
          <div slot="header">Similar Issue Suggestions</div>
          <div class="spinner-container">
            <sl-spinner></sl-spinner>
          </div>
        </sl-card>
      `;
    }

    if (this._error) {
      return html`
        <sl-alert variant="danger" open>
          <sl-icon slot="icon" name="exclamation-octagon"></sl-icon>
          ${this._error}
        </sl-alert>
      `;
    }

    if (this._totalSuggestions === 0) {
      return html`
        <sl-alert variant="primary" open>
          <sl-icon slot="icon" name="info-circle"></sl-icon>
          No similar issues found for the current filters.
        </sl-alert>
      `;
    }

    const renderTopSuggestionsText = () => {
      const count = this._topSuggestions.length;
      if (count === 0) {
        return 'There are no suggestions to display.';
      }
      if (count === 1) {
        return 'Here is the top suggestion:';
      }
      return `Here are the top ${count} suggestions:`;
    };

    return html`
      <sl-card class="table-card">
        <div slot="header">Similar Issue Suggestions</div>
        <div class="sub-header">
          You have
          <a href="/console/issues"
            ><strong
              >${this._totalSuggestions > 100
                ? '100+'
                : this._totalSuggestions}</strong
            >
            unresolved suggestions</a
          >. ${renderTopSuggestionsText()}
        </div>
        <ul class="suggestion-list">
          ${this._topSuggestions.map((pair) => {
            const pairKey = `${pair.issue1.id}-${pair.issue2.id}`;
            return html`
              <li class="suggestion-item">
                <div
                  class="issue-titles"
                  title="${pair.issue1.title} vs ${pair.issue2.title}"
                >
                  <strong>${pair.issue1.key}</strong> vs
                  <strong>${pair.issue2.key}</strong>
                </div>
                <div>
                  <sl-badge variant="neutral"
                    >${(pair.similarity * 100).toFixed(0)}%</sl-badge
                  >
                  <div class="verdict-container">
                    ${pair.similarity > 0.999
                      ? html`<sl-badge
                          variant="warning"
                          style="--sl-color-warning-text: var(--sl-color-orange-50); --sl-color-warning-600: var(--sl-color-orange-700);"
                          pill
                          >Identical</sl-badge
                        >`
                      : renderVerdict(this._aiVerdicts[pairKey])}
                  </div>
                </div>
              </li>
            `;
          })}
        </ul>
        ${this._totalSuggestions > 0
          ? html`
              <div class="see-all-container">
                <a href="/console/issues">See all...</a>
              </div>
            `
          : ''}
      </sl-card>
    `;
  }
}
