import type { PropertyValues } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { fireEvent } from "../../../common/dom/fire_event";
import "../../../components/animation/ha-fade-in";
import "../../../components/ha-alert";
import "../../../components/ha-button";
import "../../../components/ha-card";
import "../../../components/ha-icon-button";
import "../../../components/ha-spinner";
import "../../../components/ha-switch";
import "../../../components/item/ha-row-item";
import type {
  BackupAgent,
  BackupAgentConfig,
  BackupConfig,
  Retention,
} from "../../../data/backup";
import {
  CLOUD_AGENT,
  computeBackupAgentName,
  fetchBackupAgentsInfo,
  isLocalAgent,
  updateBackupConfig,
} from "../../../data/backup";
import "../../../layouts/hass-subpage";
import type { HomeAssistant, ValueChangedEvent } from "../../../types";
import { showConfirmationDialog } from "../../lovelace/custom-card-helpers";
import "./components/config/ha-backup-config-retention";
import "./components/ha-backup-data-picker";

@customElement("ha-config-backup-location")
class HaConfigBackupDetails extends LitElement {
  @property({ attribute: false }) public hass!: HomeAssistant;

  @property({ type: Boolean }) public narrow = false;

  @property({ attribute: "agent-id" }) public agentId!: string;

  @property({ attribute: false }) public config?: BackupConfig;

  @property({ attribute: false }) public agents: BackupAgent[] = [];

  @state() private _agent?: BackupAgent | null;

  @state() private _error?: string;

  protected willUpdate(changedProps: PropertyValues<this>): void {
    if (changedProps.has("agentId")) {
      if (this.agentId) {
        this._fetchAgent();
      } else {
        this._error = "Agent id not defined";
      }
    }
  }

  protected render() {
    if (!this.hass) {
      return nothing;
    }

    const encrypted = this._isEncryptionTurnedOn();

    const agentName =
      (this._agent &&
        computeBackupAgentName(
          this.hass.localize,
          this.agentId,
          this.agents
        )) ||
      this.hass.localize("ui.panel.config.backup.location.header");

    return html`
      <hass-subpage
        back-path="/config/backup/settings"
        .hass=${this.hass}
        .narrow=${this.narrow}
        .header=${agentName}
      >
        <div class="content">
          ${
            this._error &&
            html`<ha-alert alert-type="error">${this._error}</ha-alert>`
          }
          ${
            this._agent === null
              ? html`
                  <ha-alert
                    alert-type="warning"
                    .title=${this.hass.localize(
                      "ui.panel.config.backup.location.not_found"
                    )}
                  >
                    ${this.hass.localize(
                      "ui.panel.config.backup.location.not_found_description",
                      { agentId: this.agentId }
                    )}
                  </ha-alert>
                `
              : !this.agentId
                ? html`<ha-fade-in .delay=${1000}
                    ><ha-spinner></ha-spinner
                  ></ha-fade-in>`
                : html`
                    <ha-card>
                      <div class="card-header">
                        ${this.hass.localize(
                          "ui.panel.config.backup.location.configuration.title"
                        )}
                      </div>
                      ${
                        CLOUD_AGENT === this.agentId
                          ? html`
                              <div class="card-content">
                                <p>
                                  ${this.hass.localize(
                                    "ui.panel.config.backup.location.configuration.cloud_description"
                                  )}
                                </p>
                              </div>
                            `
                          : html`<ha-backup-config-retention
                              location-specific
                              .headline=${this.hass.localize(
                                `ui.panel.config.backup.location.retention_for_${isLocalAgent(this.agentId) ? "this_system" : "location"}`,
                                { location: agentName }
                              )}
                              .hass=${this.hass}
                              .retention=${
                                !this.config
                                  ? undefined
                                  : this.config.agents[this.agentId]
                                      ?.retention || null
                              }
                              @value-changed=${this._retentionChanged}
                            ></ha-backup-config-retention>`
                      }
                    </ha-card>
                    <ha-card>
                      <div class="card-header">
                        ${this.hass.localize(
                          "ui.panel.config.backup.location.encryption.title"
                        )}
                      </div>
                      <div class="card-content">
                        <p>
                          ${this.hass.localize(
                            "ui.panel.config.backup.location.encryption.description"
                          )}
                        </p>
                        ${
                          CLOUD_AGENT === this.agentId
                            ? html`
                                <ha-row-item>
                                  <span slot="headline">
                                    ${this.hass.localize(
                                      "ui.panel.config.backup.location.encryption.location_encrypted"
                                    )}
                                  </span>
                                  <span slot="supporting-text">
                                    ${this.hass.localize(
                                      "ui.panel.config.backup.location.encryption.location_encrypted_cloud_description"
                                    )}
                                  </span>
                                  <ha-button
                                    href="https://www.nabucasa.com/config/backups/"
                                    target="_blank"
                                    slot="end"
                                    rel="noreferrer noopener"
                                    appearance="plain"
                                    size="s"
                                  >
                                    ${this.hass.localize(
                                      "ui.panel.config.backup.location.encryption.location_encrypted_cloud_learn_more"
                                    )}
                                  </ha-button>
                                </ha-row-item>
                              `
                            : encrypted
                              ? html`
                                  <ha-row-item>
                                    <span slot="headline">
                                      ${this.hass.localize(
                                        "ui.panel.config.backup.location.encryption.location_encrypted"
                                      )}
                                    </span>
                                    <span slot="supporting-text">
                                      ${this.hass.localize(
                                        `ui.panel.config.backup.location.encryption.location_encrypted_description`
                                      )}
                                    </span>

                                    <ha-button
                                      slot="end"
                                      @click=${this._turnOffEncryption}
                                      variant="danger"
                                    >
                                      ${this.hass.localize(
                                        "ui.panel.config.backup.location.encryption.encryption_turn_off"
                                      )}
                                    </ha-button>
                                  </ha-row-item>
                                `
                              : html`
                                  <ha-alert
                                    alert-type="warning"
                                    .title=${this.hass.localize(
                                      "ui.panel.config.backup.location.encryption.warning_encryption_turn_off"
                                    )}
                                  >
                                    ${this.hass.localize(
                                      "ui.panel.config.backup.location.encryption.warning_encryption_turn_off_description"
                                    )}
                                  </ha-alert>
                                  <ha-row-item>
                                    <span slot="headline">
                                      ${this.hass.localize(
                                        "ui.panel.config.backup.location.encryption.location_unencrypted"
                                      )}
                                    </span>
                                    <span slot="supporting-text">
                                      ${this.hass.localize(
                                        `ui.panel.config.backup.location.encryption.location_unencrypted_description`
                                      )}
                                    </span>

                                    <ha-button
                                      slot="end"
                                      @click=${this._turnOnEncryption}
                                    >
                                      ${this.hass.localize(
                                        "ui.panel.config.backup.location.encryption.encryption_turn_on"
                                      )}
                                    </ha-button>
                                  </ha-row-item>
                                `
                        }
                      </div>
                    </ha-card>
                  `
          }
        </div>
      </hass-subpage>
    `;
  }

  private _isEncryptionTurnedOn() {
    const agentConfig = this.config?.agents[this.agentId] as
      BackupAgentConfig | undefined;

    if (!agentConfig) {
      return true;
    }
    return agentConfig.protected;
  }

  private async _fetchAgent() {
    try {
      const { agents } = await fetchBackupAgentsInfo(this.hass);
      const agent = agents.find((a) => a.agent_id === this.agentId);
      if (!agent) {
        throw new Error("Agent not found");
      }
      this._agent = agent;
    } catch (err: any) {
      this._error =
        err?.message ||
        this.hass.localize("ui.panel.config.backup.details.error");
    }
  }

  private async _updateAgentConfig(config: Partial<BackupAgentConfig>) {
    try {
      const agents = this.config?.agents || {};
      agents[this.agentId] = {
        ...(agents[this.agentId] || {}),
        ...config,
      };

      await updateBackupConfig(this.hass, {
        agents,
      });
      fireEvent(this, "ha-refresh-backup-config");
    } catch (err: any) {
      this._error = this.hass.localize(
        "ui.panel.config.backup.location.save_error",
        { error: err.message }
      );
    }
  }

  private _retentionChanged(ev: ValueChangedEvent<Retention>) {
    const retention = ev.detail.value;
    this._updateAgentConfig({
      retention,
    });
  }

  private async _updateAgentEncryption(value: boolean) {
    this._updateAgentConfig({
      protected: value,
    });
  }

  private _turnOnEncryption() {
    this._updateAgentEncryption(true);
  }

  private async _turnOffEncryption() {
    const response = await showConfirmationDialog(this, {
      title: this.hass.localize(
        "ui.panel.config.backup.location.encryption.encryption_turn_off_confirm_title"
      ),
      text: this.hass.localize(
        "ui.panel.config.backup.location.encryption.encryption_turn_off_confirm_text"
      ),
      confirmText: this.hass.localize(
        "ui.panel.config.backup.location.encryption.encryption_turn_off_confirm_action"
      ),
      dismissText: this.hass.localize("ui.common.cancel"),
      destructive: true,
    });
    if (response) {
      this._updateAgentEncryption(false);
    }
  }

  static styles = css`
    .content {
      padding: 28px 20px 0;
      max-width: 690px;
      margin: 0 auto;
      gap: var(--ha-space-6);
      display: grid;
      margin-bottom: 24px;
    }
    .card-content {
      padding: 0 20px;
    }
    .card-actions {
      display: flex;
      justify-content: flex-end;
    }
    ha-row-item {
      --ha-row-item-padding-inline: 0;
    }
    ha-row-item img {
      width: 48px;
    }
    ha-row-item ha-svg-icon[slot="start"] {
      --mdc-icon-size: 48px;
      color: var(--primary-text-color);
    }
    .warning {
      color: var(--error-color);
    }
    .warning ha-svg-icon {
      color: var(--error-color);
    }
    ha-button.danger {
      --mdc-theme-primary: var(--error-color);
    }
    ha-backup-data-picker {
      display: block;
    }
    ha-row-item::part(supporting-text) {
      white-space: wrap;
    }
    .dot {
      display: block;
      position: relative;
      width: 8px;
      height: 8px;
      background-color: var(--disabled-color);
      border-radius: var(--ha-border-radius-circle);
      flex: none;
    }
    .dot.success {
      background-color: var(--success-color);
    }
    .dot.error {
      background-color: var(--error-color);
    }
    .card-header {
      padding-bottom: 8px;
    }
    ha-spinner {
      margin: 24px auto;
    }
    ha-backup-config-retention {
      display: block;
      padding: 16px;
    }
  `;
}

declare global {
  interface HTMLElementTagNameMap {
    "ha-config-backup-location": HaConfigBackupDetails;
  }
}
