import { LitElement, html, css, unsafeCSS } from 'lit';
import { customElement, property, state } from 'lit/decorators.js';
import {
  DuplicatePair,
  executeIssueDuplicateResolution,
  IssueDuplicateResolutionRequest,
  getResolutionSuggestion,
} from '../api';
import '@shoelace-style/shoelace/dist/components/dialog/dialog.js';
import '@shoelace-style/shoelace/dist/components/button/button.js';
import '@shoelace-style/shoelace/dist/components/radio-group/radio-group.js';
import '@shoelace-style/shoelace/dist/components/radio/radio.js';
import '@shoelace-style/shoelace/dist/components/spinner/spinner.js';
import '@shoelace-style/shoelace/dist/components/input/input.js';
import '@shoelace-style/shoelace/dist/components/textarea/textarea.js';
import '@shoelace-style/shoelace/dist/components/tag/tag.js';
import '@shoelace-style/shoelace/dist/components/tab/tab.js';
import '@shoelace-style/shoelace/dist/components/tab-group/tab-group.js';
import '@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js';

import consoleStyles from '../styles/console-styles.css?inline';

type ResolutionStep = 'initial' | 'close' | 'merge' | 'deconflict';

@customElement('resolve-issue-modal')
export class ResolveIssueModal extends LitElement {
  @property({ type: Boolean }) isOpen = false;
  @property({ type: Object }) duplicatePair: DuplicatePair | null = null;

  @state() private _isSubmitting = false;
  @state() private _resolutionStep: ResolutionStep = 'initial';
  @state() private _isLoadingSuggestion = false;
  @state() private _mergeTarget: 'A' | 'B' = 'B';
  @state() private _mergedTitle = '';
  @state() private _mergedDescription = '';

  // State for Deconflict step
  @state() private _deconflictedTitle1 = '';
  @state() private _deconflictedDescription1 = '';
  @state() private _deconflictedTitle2 = '';
  @state() private _deconflictedDescription2 = '';

  @state() private _resolutionSummary = '';
  @state() private _modalTitle = 'Resolve Similar Issues';

  private updateTitleForStep(step: ResolutionStep) {
    switch (step) {
      case 'initial':
        this._modalTitle = 'Resolve Similar Issues';
        break;
      case 'close':
        this._modalTitle = 'Resolve Similar Issues → Close as Duplicate';
        break;
      case 'merge':
        this._modalTitle = 'Resolve Similar Issues → Merge Issues';
        break;
      case 'deconflict':
        this._modalTitle = 'Resolve Similar Issues → Deconflict Issues';
        break;
    }
  }

  private handleOpen() {
    this._isSubmitting = false;
    this._resolutionStep = 'initial';
    this.updateTitleForStep('initial');
  }

  private handleClose() {
    this.isOpen = false;
    this.dispatchEvent(
      new CustomEvent('on-close', { bubbles: true, composed: true })
    );
  }

  private goBack() {
    this._resolutionStep = 'initial';
    this.updateTitleForStep('initial');
  }

  private async startResolution(step: ResolutionStep) {
    this._resolutionStep = step;
    this.updateTitleForStep(step);

    // Reset previous suggestions
    this._mergedTitle = '';
    this._mergedDescription = '';
    this._deconflictedTitle1 = '';
    this._deconflictedDescription1 = '';
    this._deconflictedTitle2 = '';
    this._deconflictedDescription2 = '';

    if (step === 'merge' || step === 'deconflict') {
      if (!this.duplicatePair?.issue1 || !this.duplicatePair?.issue2) return;
      this._isLoadingSuggestion = true;
      try {
        const resolutionType = step === 'merge' ? 'merged' : 'deconflicted';
        const suggestion = await getResolutionSuggestion(
          this.duplicatePair.issue1.id,
          this.duplicatePair.issue2.id,
          resolutionType
        );

        if (step === 'merge') {
          this._mergedTitle = suggestion.merged_title || '';
          this._mergedDescription = suggestion.merged_description || '';
        } else {
          this._deconflictedTitle1 = suggestion.deconflicted_title1 || '';
          this._deconflictedDescription1 =
            suggestion.deconflicted_description1 || '';
          this._deconflictedTitle2 = suggestion.deconflicted_title2 || '';
          this._deconflictedDescription2 =
            suggestion.deconflicted_description2 || '';
        }
      } catch (error) {
        console.error('Failed to get suggestion:', error);
        // Optionally, show an error message to the user
      } finally {
        this._isLoadingSuggestion = false;
      }
    }
  }

  private async handleFinalResolve(resolutionType: string) {
    if (!this.duplicatePair) return;
    this._isSubmitting = true;

    const { issue1, issue2 } = this.duplicatePair;
    let resolutionData: IssueDuplicateResolutionRequest;
    let resolutionSummary = '';

    switch (resolutionType) {
      case 'CLOSE_A':
        resolutionData = {
          issue1_id: issue1.id,
          issue2_id: issue2.id,
          resolution: 'close_a',
        };
        resolutionSummary = `Closed ${issue1.key} as duplicate of ${issue2.key}.`;
        break;
      case 'CLOSE_B':
        resolutionData = {
          issue1_id: issue1.id,
          issue2_id: issue2.id,
          resolution: 'close_b',
        };
        resolutionSummary = `Closed ${issue2.key} as duplicate of ${issue1.key}.`;
        break;
      case 'MERGE':
        resolutionData = {
          issue1_id: issue1.id,
          issue2_id: issue2.id,
          resolution:
            this._mergeTarget === 'A' ? 'merge_b_to_a' : 'merge_a_to_b',
          resulting_issue_1_title:
            this._mergeTarget === 'A' ? this._mergedTitle : undefined,
          resulting_issue_1_description:
            this._mergeTarget === 'A' ? this._mergedDescription : undefined,
          resulting_issue_2_title:
            this._mergeTarget === 'B' ? this._mergedTitle : undefined,
          resulting_issue_2_description:
            this._mergeTarget === 'B' ? this._mergedDescription : undefined,
        };
        resolutionSummary = `Merged ${issue1.key} and ${issue2.key}.`;
        break;
      case 'DECONFLICT':
        resolutionData = {
          issue1_id: issue1.id,
          issue2_id: issue2.id,
          resolution: 'deconflict',
          resulting_issue_1_title: this._deconflictedTitle1,
          resulting_issue_1_description: this._deconflictedDescription1,
          resulting_issue_2_title: this._deconflictedTitle2,
          resulting_issue_2_description: this._deconflictedDescription2,
        };
        resolutionSummary = `Deconflicted ${issue1.key} and ${issue2.key}.`;
        break;
      case 'UNRELATED':
        resolutionData = {
          issue1_id: issue1.id,
          issue2_id: issue2.id,
          resolution: 'unrelated',
        };
        resolutionSummary = `Marked ${issue1.key} and ${issue2.key} as unrelated.`;
        break;
      default:
        // Handle other cases if necessary
        this._isSubmitting = false;
        return;
    }

    try {
      await executeIssueDuplicateResolution(resolutionData);
      this.dispatchEvent(
        new CustomEvent('on-resolved', {
          bubbles: true,
          composed: true,
          detail: { summary: resolutionSummary },
        })
      );
      this.handleClose();
    } catch (error) {
      console.error('Failed to resolve duplicate:', error);
      // TODO: Add a user-facing error notification (e.g., a toast)
    } finally {
      this._isSubmitting = false;
    }
  }

  // Step 1: Initial choice
  private renderInitialStep() {
    const actions = [
      {
        id: 'close',
        title: 'Close as Duplicate',
        description:
          'One issue will be closed, the other will remain. You will choose which one to close in the next step.',
        handler: () => this.startResolution('close'),
      },
      {
        id: 'merge',
        title: 'Merge Issues',
        description:
          'Combine both issues into a single issue. You will edit the new title and description in the next step.',
        handler: () => this.startResolution('merge'),
      },
      {
        id: 'deconflict',
        title: 'Deconflict Issues',
        description:
          'Edit the titles and descriptions of both issues to make them distinct. Both issues will remain open.',
        handler: () => this.startResolution('deconflict'),
      },
      {
        id: 'unrelated',
        title: 'Mark as Unrelated',
        description:
          'Mark the issues as unrelated. This action is immediate and requires no further steps.',
        handler: () => this.handleFinalResolve('UNRELATED'),
      },
    ];

    return html`
      <div class="step-container">
        <div class="initial-options-group">
          ${actions.map(
            (action) => html`
              <div class="action-card" @click=${action.handler}>
                <div class="action-title">${action.title}</div>
                <div class="action-description">${action.description}</div>
              </div>
            `
          )}
        </div>
      </div>
    `;
  }

  // Step 2a: Close
  private renderCloseStep() {
    const issueA = this.duplicatePair?.issue1;
    const issueB = this.duplicatePair?.issue2;
    return html`
      <div class="step-container">
        <p>Select which issue to close. The other will remain open.</p>
        <div class="close-options-group">
          <div
            class="action-card"
            @click=${() => this.handleFinalResolve('CLOSE_A')}
          >
            <div class="action-title">
              Close ${issueA?.key}: ${issueA?.title}
            </div>
            <div class="action-description">
              This will mark ${issueA?.key} as a duplicate of ${issueB?.key} and
              close it. ${issueB?.key} will remain open.
            </div>
          </div>
          <div
            class="action-card"
            @click=${() => this.handleFinalResolve('CLOSE_B')}
          >
            <div class="action-title">
              Close ${issueB?.key}: ${issueB?.title}
            </div>
            <div class="action-description">
              This will mark ${issueB?.key} as a duplicate of ${issueA?.key} and
              close it. ${issueA?.key} will remain open.
            </div>
          </div>
        </div>
        <div class="footer-buttons">
          <sl-button @click="${this.goBack}">Back</sl-button>
        </div>
      </div>
    `;
  }

  // Step 2b: Merge
  private renderMergeStep() {
    const issueA = this.duplicatePair?.issue1;
    const issueB = this.duplicatePair?.issue2;
    return html`
      <div class="step-container">
        <h2 class="issue-comparison-header">Original Issues</h2>
        <div class="comparison-container">
          <div class="issue-panel">
            <div class="issue-header">
              <a href="${issueA?.url}" target="_blank">${issueA?.key}</a>
            </div>
            <h3 class="issue-title">${issueA?.title}</h3>
            <div class="issue-description">${issueA?.description}</div>
          </div>
          <div class="issue-panel">
            <div class="issue-header">
              <a href="${issueB?.url}" target="_blank">${issueB?.key}</a>
            </div>
            <h3 class="issue-title">${issueB?.title}</h3>
            <div class="issue-description">${issueB?.description}</div>
          </div>
        </div>

        <h2 class="issue-comparison-header">Proposed Issue</h2>
        ${this._isLoadingSuggestion
          ? html`<div class="loading-suggestion">
              <sl-spinner></sl-spinner>
              <div>Generating suggestion...</div>
            </div>`
          : html`
              <div class="form-group">
                <sl-input
                  .value=${this._mergedTitle}
                  @sl-input=${(e: any) => (this._mergedTitle = e.target.value)}
                ></sl-input>
                <sl-textarea
                  .value=${this._mergedDescription}
                  @sl-input=${(e: any) =>
                    (this._mergedDescription = e.target.value)}
                  rows="8"
                ></sl-textarea>
              </div>
            `}

        <div class="footer-buttons">
          <sl-button @click="${this.goBack}">Back</sl-button>
          <sl-button-group label="Merge Direction">
            <sl-button
              variant=${this._mergeTarget === 'A' ? 'primary' : 'default'}
              @click=${() => (this._mergeTarget = 'A')}
              ?disabled=${this._isLoadingSuggestion}
              >Merge into ${issueA?.key}</sl-button
            >
            <sl-button
              variant=${this._mergeTarget === 'B' ? 'primary' : 'default'}
              @click=${() => (this._mergeTarget = 'B')}
              ?disabled=${this._isLoadingSuggestion}
              >Merge into ${issueB?.key}</sl-button
            >
          </sl-button-group>
          <sl-button
            variant="primary"
            .loading=${this._isSubmitting}
            ?disabled=${this._isLoadingSuggestion}
            @click="${() => this.handleFinalResolve('MERGE')}"
            >Resolve by Merging</sl-button
          >
        </div>
      </div>
    `;
  }

  // Step 2c: Deconflict
  private renderDeconflictStep() {
    const issueA = this.duplicatePair?.issue1;
    const issueB = this.duplicatePair?.issue2;
    return html`
      <div class="step-container">
        <h2 class="issue-comparison-header">Original Issues</h2>
        <div class="comparison-container">
          <div class="issue-panel">
            <div class="issue-header">
              <a href="${issueA?.url}" target="_blank">${issueA?.key}</a>
            </div>
            <h3 class="issue-title">${issueA?.title}</h3>
            <div class="issue-description">${issueA?.description}</div>
          </div>
          <div class="issue-panel">
            <div class="issue-header">
              <a href="${issueB?.url}" target="_blank">${issueB?.key}</a>
            </div>
            <h3 class="issue-title">${issueB?.title}</h3>
            <div class="issue-description">${issueB?.description}</div>
          </div>
        </div>

        <h2 class="issue-comparison-header">Proposed Changes</h2>
        ${this._isLoadingSuggestion
          ? html`<div class="loading-suggestion">
              <sl-spinner></sl-spinner>
              <div>Generating suggestion...</div>
            </div>`
          : html`
              <div class="comparison-container">
                <div class="issue-panel form-group">
                  <div class="issue-header">${issueA?.key}</div>
                  <sl-input
                    .value=${this._deconflictedTitle1}
                    @sl-input=${(e: any) =>
                      (this._deconflictedTitle1 = e.target.value)}
                  ></sl-input>
                  <sl-textarea
                    .value=${this._deconflictedDescription1}
                    @sl-input=${(e: any) =>
                      (this._deconflictedDescription1 = e.target.value)}
                    rows="8"
                  ></sl-textarea>
                </div>
                <div class="issue-panel form-group">
                  <div class="issue-header">${issueB?.key}</div>
                  <sl-input
                    .value=${this._deconflictedTitle2}
                    @sl-input=${(e: any) =>
                      (this._deconflictedTitle2 = e.target.value)}
                  ></sl-input>
                  <sl-textarea
                    .value=${this._deconflictedDescription2}
                    @sl-input=${(e: any) =>
                      (this._deconflictedDescription2 = e.target.value)}
                    rows="8"
                  ></sl-textarea>
                </div>
              </div>
            `}

        <div class="footer-buttons">
          <sl-button @click="${this.goBack}">Back</sl-button>
          <sl-button
            variant="primary"
            .loading=${this._isSubmitting}
            ?disabled=${this._isLoadingSuggestion}
            @click="${() => this.handleFinalResolve('DECONFLICT')}"
            >Resolve by Deconflicting</sl-button
          >
        </div>
      </div>
    `;
  }

  render() {
    let content;
    switch (this._resolutionStep) {
      case 'close':
        content = this.renderCloseStep();
        break;
      case 'merge':
        content = this.renderMergeStep();
        break;
      case 'deconflict':
        content = this.renderDeconflictStep();
        break;
      default:
        content = this.renderInitialStep();
    }

    const issue1 = this.duplicatePair?.issue1;
    const issue2 = this.duplicatePair?.issue2;

    return html`
      <sl-dialog
        label=${this._modalTitle}
        .open=${this.isOpen}
        @sl-show=${this.handleOpen}
        @sl-after-hide=${this.handleClose}
        @sl-initial-focus=${(e: Event) => e.preventDefault()}
        class="resolve-issue-dialog large"
      >
        ${this._resolutionStep !== 'merge' &&
        this._resolutionStep !== 'deconflict'
          ? html`
              <div class="comparison-container">
                <div class="issue-panel">
                  <div class="issue-header">
                    <a href="${issue1?.url}" target="_blank">${issue1?.key}</a>
                  </div>
                  <h3 class="issue-title">${issue1?.title}</h3>
                  <div class="issue-description">${issue1?.description}</div>
                </div>
                <div class="issue-panel">
                  <div class="issue-header">
                    <a href="${issue2?.url}" target="_blank">${issue2?.key}</a>
                  </div>
                  <h3 class="issue-title">${issue2?.title}</h3>
                  <div class="issue-description">${issue2?.description}</div>
                </div>
              </div>
            `
          : ''}
        ${content}
      </sl-dialog>
    `;
  }

  static styles = [
    unsafeCSS(consoleStyles),
    css`
      h2 {
        position: relative;
        text-align: left;
        font-size: 1.2rem;
        font-weight: 300;
        margin-bottom: 1rem;
      }

      .initial-options-group,
      .close-options-group {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 1rem;
        margin-top: 1rem;
      }

      @media (min-width: 992px) {
        .initial-options-group {
          grid-template-columns: repeat(4, 1fr);
        }
      }

      .action-card {
        border: 1px solid var(--sl-color-neutral-300);
        border-radius: var(--sl-border-radius-medium);
        padding: 1rem;
        cursor: pointer;
        transition: all 0.2s ease;
      }
      .action-card:hover {
        background-color: var(--sl-color-primary-50);
        border-color: var(--sl-color-primary-300);
      }
      .action-title {
        font-weight: var(--sl-font-weight-semibold);
      }
      .action-description {
        font-size: var(--sl-font-size-small);
        color: var(--sl-color-neutral-600);
        margin-top: 0.5rem;
      }
      .footer-buttons {
        display: flex;
        justify-content: space-between;
        margin-top: 1.5rem;
      }
      sl-radio-group {
        margin-bottom: 1rem;
      }
      sl-radio-group::part(label) {
        font-weight: bold;
      }

      .issue-header {
        font-size: var(--sl-font-size-medium);
        margin-bottom: var(--sl-spacing-small);
      }
      .issue-title {
        font-size: var(--sl-font-size-medium);
        font-weight: var(--sl-font-weight-semibold);
        margin-top: 0;
        margin-bottom: var(--sl-spacing-medium);
      }
      .issue-description {
        font-size: var(--sl-font-size-small);
        color: var(--sl-color-neutral-700);
        background-color: var(--sl-color-neutral-100);
        border: 1px solid var(--sl-color-neutral-200);
        border-radius: var(--sl-border-radius-medium);
        padding: var(--sl-spacing-medium);
        white-space: pre-wrap;
        word-wrap: break-word;
        max-height: 300px;
        overflow-y: auto;
      }
      .form-group {
        display: flex;
        flex-direction: column;
        gap: 1rem;
      }
      sl-textarea::part(textarea) {
        font-size: var(--sl-font-size-small);
        max-height: 200px;
        overflow-y: auto;
      }
      .loading-suggestion {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        padding: 2rem;
        gap: 1rem;
        color: var(--sl-color-neutral-600);
      }
    `,
  ];
}
