import { mdiDownload } from "@mdi/js";
import type { CSSResultGroup, PropertyValues, TemplateResult } from "lit";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { isComponentLoaded } from "../../../common/config/is_component_loaded";
import { extractSearchParam } from "../../../common/url/search-params";
import "../../../components/ha-analytics";
import "../../../components/ha-button";
import "../../../components/ha-card";
import "../../../components/ha-spinner";
import "../../../components/ha-svg-icon";
import "../../../components/ha-switch";
import type { HaSwitch } from "../../../components/ha-switch";
import "../../../components/item/ha-row-item";
import type { Analytics } from "../../../data/analytics";
import {
  getAnalyticsDetails,
  setAnalyticsPreferences,
} from "../../../data/analytics";
import { getSignedPath } from "../../../data/auth";
import { getConfigEntries } from "../../../data/config_entries";
import type { LabPreviewFeature } from "../../../data/labs";
import { subscribeLabFeature } from "../../../data/labs";
import {
  fetchZwaveDataCollectionStatus,
  setZwaveDataCollectionPreference,
} from "../../../data/zwave_js";
import { SubscribeMixin } from "../../../mixins/subscribe-mixin";
import { haStyle } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types";
import { documentationUrl } from "../../../util/documentation-url";
import { fileDownload } from "../../../util/file_download";

@customElement("ha-config-analytics")
class ConfigAnalytics extends SubscribeMixin(LitElement) {
  @property({ attribute: false }) public hass!: HomeAssistant;

  @state() private _analyticsDetails?: Analytics;

  @state() private _error?: string;

  @state() private _snapshotsLabEnabled = false;

  @state() private _zwaveEntryId?: string;

  @state() private _zwaveDataCollectionOptIn?: boolean;

  @state() private _highlightedSection?: string;

  protected render(): TemplateResult {
    const error = this._error
      ? this._error
      : !isComponentLoaded(this.hass.config, "analytics")
        ? "Analytics integration not loaded"
        : undefined;

    return html`
      <ha-card
        outlined
        .header=${
          this.hass.localize("ui.panel.config.analytics.header") ||
          "Home Assistant analytics"
        }
      >
        <div class="card-content">
          ${error ? html`<div class="error">${error}</div>` : nothing}
          <p>
            ${this.hass.localize("ui.panel.config.analytics.intro")}
            <a
              href=${documentationUrl(this.hass, "/integrations/analytics/")}
              target="_blank"
              rel="noreferrer"
              >${this.hass.localize("ui.panel.config.analytics.learn_more")}</a
            >.
          </p>
          <ha-analytics
            translation_key_panel="config"
            @analytics-preferences-changed=${this._preferencesChanged}
            .localize=${this.hass.localize}
            .analytics=${this._analyticsDetails}
          ></ha-analytics>
        </div>
      </ha-card>
      ${
        this._snapshotsLabEnabled
          ? html`<ha-card
              outlined
              .header=${this.hass.localize(
                "ui.panel.config.analytics.preferences.snapshots.header"
              )}
            >
              <div class="card-content">
                <p>
                  ${this.hass.localize(
                    "ui.panel.config.analytics.preferences.snapshots.info",
                    {
                      data_use_statement: html`<a
                        href="https://www.openhomefoundation.org/device-database-data-use-statement"
                        target="_blank"
                        rel="noreferrer"
                        >${this.hass.localize(
                          "ui.panel.config.analytics.preferences.snapshots.data_use_statement"
                        )}</a
                      >`,
                    }
                  )}
                </p>
                <ha-row-item>
                  <span slot="headline">
                    ${this.hass.localize(
                      `ui.panel.config.analytics.preferences.snapshots.title`
                    )}
                  </span>
                  <span slot="supporting-text">
                    ${this.hass.localize(
                      `ui.panel.config.analytics.preferences.snapshots.description`
                    )}
                  </span>
                  <ha-switch
                    slot="end"
                    @change=${this._handleDeviceRowClick}
                    .checked=${!!this._analyticsDetails?.preferences.snapshots}
                    .disabled=${this._analyticsDetails === undefined}
                  ></ha-switch>
                </ha-row-item>
              </div>
              <div class="card-actions">
                <ha-button
                  size="s"
                  appearance="plain"
                  @click=${this._downloadDeviceInfo}
                >
                  <ha-svg-icon slot="start" .path=${mdiDownload}></ha-svg-icon>
                  ${this.hass.localize(
                    "ui.panel.config.analytics.download_device_info"
                  )}
                </ha-button>
              </div>
            </ha-card>`
          : nothing
      }
      ${
        this._zwaveEntryId !== undefined
          ? html`<ha-card
              outlined
              data-section="zwave"
              class=${this._highlightedSection === "zwave" ? "highlighted" : ""}
              .header=${this.hass.localize(
                "ui.panel.config.zwave_js.dashboard.data_collection.title"
              )}
            >
              <div class="card-content">
                <p>
                  ${this.hass.localize(
                    "ui.panel.config.zwave_js.dashboard.data_collection.info",
                    {
                      documentation_link: html`<a
                        target="_blank"
                        href="https://zwave-js.github.io/node-zwave-js/#/data-collection/data-collection"
                        rel="noreferrer"
                        >${this.hass.localize(
                          "ui.panel.config.zwave_js.dashboard.data_collection.documentation_link"
                        )}</a
                      >`,
                    }
                  )}
                </p>
                <ha-row-item>
                  <span slot="headline">
                    ${this.hass.localize(
                      "ui.panel.config.zwave_js.dashboard.data_collection.toggle_title"
                    )}
                  </span>
                  <span slot="supporting-text">
                    ${this.hass.localize(
                      "ui.panel.config.zwave_js.dashboard.data_collection.toggle_description"
                    )}
                  </span>
                  ${
                    this._zwaveDataCollectionOptIn !== undefined
                      ? html`
                          <ha-switch
                            slot="end"
                            @change=${this._zwaveDataCollectionToggled}
                            .checked=${this._zwaveDataCollectionOptIn === true}
                          ></ha-switch>
                        `
                      : html`<ha-spinner slot="end" size="small"></ha-spinner>`
                  }
                </ha-row-item>
              </div>
            </ha-card>`
          : nothing
      }
    `;
  }

  public hassSubscribe() {
    return [
      subscribeLabFeature(
        this.hass.connection,
        "analytics",
        "snapshots",
        (feature: LabPreviewFeature) => {
          this._snapshotsLabEnabled = feature.enabled;
        }
      ),
    ];
  }

  protected firstUpdated(changedProps: PropertyValues<this>) {
    super.firstUpdated(changedProps);
    const section = extractSearchParam("section");
    if (section) {
      this._highlightedSection = section;
    }
    if (isComponentLoaded(this.hass.config, "analytics")) {
      this._load();
    }
  }

  private async _load() {
    this._error = undefined;
    try {
      this._analyticsDetails = await getAnalyticsDetails(this.hass);
    } catch (err: any) {
      this._error = err.message || err;
    }
    this._loadZwaveDataCollection();
  }

  private async _loadZwaveDataCollection() {
    if (!isComponentLoaded(this.hass.config, "zwave_js")) {
      return;
    }
    try {
      const entries = await getConfigEntries(this.hass, {
        domain: "zwave_js",
      });
      const entry = entries.find((e) => !e.disabled_by);
      if (entry) {
        this._zwaveEntryId = entry.entry_id;
        const status = await fetchZwaveDataCollectionStatus(
          this.hass,
          entry.entry_id
        );
        this._zwaveDataCollectionOptIn =
          status.opted_in === true || status.enabled === true;
        if (this._highlightedSection === "zwave") {
          this.updateComplete.then(() => {
            this._scrollToSection("zwave");
          });
        }
      }
    } catch {
      // Z-Wave data collection status is optional
    }
  }

  private _scrollToSection(section: string): void {
    // eslint-disable-next-line lit/prefer-query-decorators
    const card = this.shadowRoot?.querySelector(
      `[data-section="${section}"]`
    ) as HTMLElement;
    if (card) {
      card.scrollIntoView({ behavior: "smooth", block: "center" });
      setTimeout(() => {
        this._highlightedSection = undefined;
      }, 3000);
    }
  }

  private async _save() {
    this._error = undefined;
    try {
      await setAnalyticsPreferences(
        this.hass,
        this._analyticsDetails?.preferences || {}
      );
    } catch (err: any) {
      this._error = err.message || err;
    }
  }

  private _handleDeviceRowClick(ev: Event) {
    const target = ev.target as HaSwitch;

    this._analyticsDetails = {
      ...this._analyticsDetails!,
      preferences: {
        ...this._analyticsDetails!.preferences,
        snapshots: target.checked,
      },
    };
    this._save();
  }

  private _zwaveDataCollectionToggled(ev: Event) {
    setZwaveDataCollectionPreference(
      this.hass,
      this._zwaveEntryId!,
      (ev.target as HTMLInputElement).checked
    );
  }

  private _preferencesChanged(event: CustomEvent): void {
    this._analyticsDetails = {
      ...this._analyticsDetails!,
      preferences: event.detail.preferences,
    };
    this._save();
  }

  private async _downloadDeviceInfo(): Promise<void> {
    const signedPath = await getSignedPath(this.hass, "/api/analytics/devices");
    fileDownload(signedPath.path);
  }

  static get styles(): CSSResultGroup {
    return [
      haStyle,
      css`
        .error {
          color: var(--error-color);
        }

        p {
          margin-top: 0;
        }
        ha-card:not(:first-of-type) {
          margin-top: 24px;
        }
        ha-row-item {
          --ha-row-item-padding-inline: 0;
        }
        ha-card {
          transition: box-shadow 0.3s ease;
        }
        ha-card.highlighted {
          animation: highlight-fade 2.5s ease-out forwards;
        }
        @keyframes highlight-fade {
          0% {
            box-shadow:
              0 0 0 var(--ha-border-width-md) var(--primary-color),
              0 0 12px rgba(var(--rgb-primary-color), 0.4);
          }
          100% {
            box-shadow:
              0 0 0 var(--ha-border-width-md) transparent,
              0 0 0 transparent;
          }
        }
      `,
    ];
  }
}

declare global {
  interface HTMLElementTagNameMap {
    "ha-config-analytics": ConfigAnalytics;
  }
}
