import * as plugins from '../../../plugins.js';
import * as appstate from '../../../appstate.js';
import { viewHostCss } from '../../shared/index.js';
import {
  DeesElement,
  customElement,
  html,
  state,
  css,
  cssManager,
  type TemplateResult,
} from '@design.estate/dees-element';

@customElement('gitops-view-connections')
export class GitopsViewConnections extends DeesElement {
  @state()
  accessor connectionsState: appstate.IConnectionsState = {
    connections: [],
    activeConnectionId: null,
  };

  private _autoRefreshHandler: () => void;

  constructor() {
    super();
    const sub = appstate.connectionsStatePart
      .select((s) => s)
      .subscribe((s) => { this.connectionsState = s; });
    this.rxSubscriptions.push(sub);

    this._autoRefreshHandler = () => this.handleAutoRefresh();
    document.addEventListener('gitops-auto-refresh', this._autoRefreshHandler);
  }

  public override disconnectedCallback() {
    super.disconnectedCallback();
    document.removeEventListener('gitops-auto-refresh', this._autoRefreshHandler);
  }

  private handleAutoRefresh(): void {
    this.refresh();
  }

  public static styles = [
    cssManager.defaultStyles,
    viewHostCss,
  ];

  public render(): TemplateResult {
    return html`
      <div class="view-title">Connections</div>
      <div class="view-description">Manage your Gitea and GitLab provider connections</div>
      <div class="toolbar">
        <dees-button @click=${() => this.addConnection()}>Add Connection</dees-button>
        <dees-button @click=${() => this.refresh()}>Refresh</dees-button>
      </div>
      <dees-table
        .heading1=${'Provider Connections'}
        .heading2=${'Configure connections to Gitea and GitLab instances'}
        .data=${this.connectionsState.connections}
        .displayFunction=${(item: any) => ({
          Name: item.name,
          Type: item.providerType,
          URL: item.baseUrl,
          'Group Filter': item.groupFilter || '-',
          Status: item.status,
          Created: new Date(item.createdAt).toLocaleDateString(),
        })}
        .dataActions=${[
          {
            name: 'Edit',
            iconName: 'lucide:edit',
            type: ['inRow', 'contextmenu'],
            actionFunc: async ({ item }: any) => { await this.editConnection(item); },
          },
          {
            name: 'Test',
            iconName: 'lucide:plug',
            type: ['inRow', 'contextmenu'],
            actionFunc: async ({ item }: any) => {
              await appstate.connectionsStatePart.dispatchAction(
                appstate.testConnectionAction,
                { connectionId: item.id },
              );
            },
          },
          {
            name: 'Pause/Resume',
            iconName: 'lucide:pauseCircle',
            type: ['inRow', 'contextmenu'],
            actionFunc: async ({ item }: any) => {
              const isPaused = item.status === 'paused';
              const actionLabel = isPaused ? 'Resume' : 'Pause';
              await plugins.deesCatalog.DeesModal.createAndShow({
                heading: `${actionLabel} Connection`,
                content: html`<p style="color: #fff;">Are you sure you want to ${actionLabel.toLowerCase()} connection "${item.name}"?</p>`,
                menuOptions: [
                  { name: 'Cancel', action: async (modal: any) => { modal.destroy(); } },
                  {
                    name: actionLabel,
                    action: async (modal: any) => {
                      await appstate.connectionsStatePart.dispatchAction(
                        appstate.pauseConnectionAction,
                        { connectionId: item.id, paused: !isPaused },
                      );
                      modal.destroy();
                    },
                  },
                ],
              });
            },
          },
          {
            name: 'Delete',
            iconName: 'lucide:trash2',
            type: ['inRow', 'contextmenu'],
            actionFunc: async ({ item }: any) => {
              await plugins.deesCatalog.DeesModal.createAndShow({
                heading: 'Delete Connection',
                content: html`<p style="color: #fff;">Are you sure you want to delete connection "${item.name}"?</p>`,
                menuOptions: [
                  { name: 'Cancel', action: async (modal: any) => { modal.destroy(); } },
                  {
                    name: 'Delete',
                    action: async (modal: any) => {
                      await appstate.connectionsStatePart.dispatchAction(
                        appstate.deleteConnectionAction,
                        { connectionId: item.id },
                      );
                      modal.destroy();
                    },
                  },
                ],
              });
            },
          },
        ]}
      ></dees-table>
    `;
  }

  async firstUpdated() {
    await this.refresh();
  }

  private async refresh() {
    await appstate.connectionsStatePart.dispatchAction(appstate.fetchConnectionsAction, null);
  }

  private async editConnection(item: any) {
    await plugins.deesCatalog.DeesModal.createAndShow({
      heading: 'Edit Connection',
      content: html`
        <style>
          .form-row { margin-bottom: 16px; }
          .form-info { font-size: 13px; color: #888; margin-bottom: 16px; }
        </style>
        <div class="form-info">Provider: ${item.providerType}</div>
        <div class="form-row">
          <dees-input-text .label=${'Name'} .key=${'name'} .value=${item.name}></dees-input-text>
        </div>
        <div class="form-row">
          <dees-input-text .label=${'Base URL'} .key=${'baseUrl'} .value=${item.baseUrl}></dees-input-text>
        </div>
        <div class="form-row">
          <dees-input-text .label=${'API Token (leave empty to keep current)'} .key=${'token'} type="password"></dees-input-text>
        </div>
        <div class="form-row">
          <dees-input-text .label=${'Group Filter (optional)'} .key=${'groupFilter'} .value=${item.groupFilter || ''} .description=${'Restricts which repos this connection can see (e.g. an org name or GitLab group path). Does not affect where synced repos are placed.'}></dees-input-text>
        </div>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (modal: any) => { modal.destroy(); } },
        {
          name: 'Save',
          action: async (modal: any) => {
            const inputs = modal.shadowRoot.querySelectorAll('dees-input-text');
            const data: any = {};
            for (const input of inputs) {
              data[input.key] = input.value || '';
            }
            await appstate.connectionsStatePart.dispatchAction(
              appstate.updateConnectionAction,
              {
                connectionId: item.id,
                name: data.name,
                baseUrl: data.baseUrl,
                groupFilter: data.groupFilter,
                ...(data.token ? { token: data.token } : {}),
              },
            );
            modal.destroy();
          },
        },
      ],
    });
  }

  private async addConnection() {
    await plugins.deesCatalog.DeesModal.createAndShow({
      heading: 'Add Connection',
      content: html`
        <style>
          .form-row { margin-bottom: 16px; }
        </style>
        <div class="form-row">
          <dees-input-text .label=${'Name'} .key=${'name'}></dees-input-text>
        </div>
        <div class="form-row">
          <dees-input-dropdown
            .label=${'Provider Type'}
            .key=${'providerType'}
            .options=${[
              { option: 'gitea', key: 'gitea' },
              { option: 'gitlab', key: 'gitlab' },
            ]}
            .selectedOption=${{ option: 'gitea', key: 'gitea' }}
          ></dees-input-dropdown>
        </div>
        <div class="form-row">
          <dees-input-text .label=${'Base URL'} .key=${'baseUrl'}></dees-input-text>
        </div>
        <div class="form-row">
          <dees-input-text .label=${'API Token'} .key=${'token'} type="password"></dees-input-text>
        </div>
        <div class="form-row">
          <dees-input-text .label=${'Group Filter (optional)'} .key=${'groupFilter'} .description=${'Restricts which repos this connection can see (e.g. an org name or GitLab group path). Does not affect where synced repos are placed.'}></dees-input-text>
        </div>
      `,
      menuOptions: [
        { name: 'Cancel', action: async (modal: any) => { modal.destroy(); } },
        {
          name: 'Add',
          action: async (modal: any) => {
            const inputs = modal.shadowRoot.querySelectorAll('dees-input-text, dees-input-dropdown');
            const data: any = {};
            for (const input of inputs) {
              if (input.key === 'providerType') {
                data[input.key] = input.selectedOption?.key || 'gitea';
              } else {
                data[input.key] = input.value || '';
              }
            }
            await appstate.connectionsStatePart.dispatchAction(
              appstate.createConnectionAction,
              {
                name: data.name,
                providerType: data.providerType,
                baseUrl: data.baseUrl,
                token: data.token,
                groupFilter: data.groupFilter || undefined,
              },
            );
            modal.destroy();
          },
        },
      ],
    });
  }
}
