import { ResizeController } from "@lit-labs/observers/resize-controller";
import { mdiPencil } from "@mdi/js";
import type { CSSResultGroup, PropertyValues } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { styleMap } from "lit/directives/style-map";
import { atLeastVersion } from "../../common/config/version";
import { navigate } from "../../common/navigate";
import { debounce } from "../../common/util/debounce";
import "../../components/ha-button";
import "../../components/ha-svg-icon";
import { updateAreaRegistryEntry } from "../../data/area/area_registry";
import { updateDeviceRegistryEntry } from "../../data/device/device_registry";
import {
  fetchFrontendSystemData,
  saveFrontendSystemData,
  type HomeFrontendSystemData,
} from "../../data/frontend";
import type { LovelaceDashboardStrategyConfig } from "../../data/lovelace/config/types";
import { mdiHomeAssistant } from "../../resources/home-assistant-logo-svg";
import type { HomeAssistant, PanelInfo, Route } from "../../types";
import { showToast } from "../../util/toast";
import { showAreaRegistryDetailDialog } from "../config/areas/show-dialog-area-registry-detail";
import { showDeviceRegistryDetailDialog } from "../config/devices/device-registry-detail/show-dialog-device-registry-detail";
import { showAddIntegrationDialog } from "../config/integrations/show-add-integration-dialog";
import "../lovelace/hui-root";
import type { ExtraActionItem } from "../lovelace/hui-root";
import {
  checkStrategyShouldRegenerate,
  generateLovelaceDashboardStrategy,
} from "../lovelace/strategies/get-strategy";
import type { Lovelace } from "../lovelace/types";
import { showEditHomeDialog } from "./dialogs/show-dialog-edit-home";
import { showNewOverviewDialog } from "./dialogs/show-dialog-new-overview";
import { hasLegacyOverviewPanel } from "../../data/panel";

@customElement("ha-panel-home")
class PanelHome extends LitElement {
  @property({ attribute: false }) public hass!: HomeAssistant;

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

  @property({ attribute: false }) public route?: Route;

  @property({ attribute: false }) public panel?: PanelInfo;

  @state() private _lovelace?: Lovelace;

  @state() private _config: FrontendSystemData["home"] = {};

  @state() private _extraActionItems?: ExtraActionItem[];

  @query(".banner") private _banner?: HTMLElement;

  private _loadConfigPromise?: Promise<void>;

  private get _showBanner(): boolean {
    // Don't show if already dismissed
    if (this._config.welcome_banner_dismissed) {
      return false;
    }
    // Don't show if HA is not running
    if (this.hass.config.state !== "RUNNING") {
      return false;
    }
    // Show banner only for users who:
    // 1. Were onboarded before 2026.2 (or have no onboarded_version)
    // 2. Don't have a custom "lovelace" dashboard (old overview)
    const onboardedVersion = this.hass.systemData?.onboarded_version;
    const isNewInstance =
      onboardedVersion && atLeastVersion(onboardedVersion, 2026, 2);
    const hasOldOverview = hasLegacyOverviewPanel(this.hass);
    return !isNewInstance && !hasOldOverview;
  }

  private _bannerHeight = new ResizeController(this, {
    target: null,
    callback: (entries) =>
      (entries[0]?.target as HTMLElement | undefined)?.offsetHeight ?? 0,
  });

  public willUpdate(changedProps: PropertyValues<this>) {
    super.willUpdate(changedProps);
    // Initial setup
    if (!this.hasUpdated) {
      this._setup();
      return;
    }

    if (changedProps.has("route")) {
      this._updateExtraActionItems();
    }

    if (!changedProps.has("hass")) {
      return;
    }

    const oldHass = changedProps.get("hass") as this["hass"] | undefined;
    if (!oldHass) {
      return;
    }

    // Locale changed: regenerate to refresh translated content
    if (oldHass.localize !== this.hass.localize) {
      this._setLovelace();
      return;
    }

    if (this.hass.config.state !== "RUNNING") {
      return;
    }

    // Home Assistant just started: run the full setup
    if (oldHass.config.state !== "RUNNING") {
      this._setup();
      return;
    }

    // A registry the strategy depends on changed: regenerate
    if (
      checkStrategyShouldRegenerate(
        "dashboard",
        this._strategyConfig.strategy,
        oldHass,
        this.hass
      )
    ) {
      this._debounceRegenerateStrategy();
    }
  }

  private async _setup() {
    this._updateExtraActionItems();
    this._loadConfigPromise = this._loadConfig();
    await this._loadConfigPromise;
    this._setLovelace();
  }

  private async _loadConfig() {
    try {
      const [_, data] = await Promise.all([
        this.hass.loadFragmentTranslation("lovelace"),
        fetchFrontendSystemData(this.hass.connection, "home"),
      ]);
      this._config = data || {};
    } catch (err) {
      // eslint-disable-next-line no-console
      console.error("Failed to load favorites:", err);
      this._config = {};
    }
  }

  private _debounceRegenerateStrategy = debounce(
    () => this._regenerateStrategyConfig(),
    200
  );

  private _regenerateStrategyConfig() {
    // If on an area view that no longer exists, redirect to overview
    const path = this.route?.path?.split("/")[1];
    if (path?.startsWith("areas-")) {
      const areaId = path.replace("areas-", "");
      if (!this.hass.areas[areaId]) {
        navigate("/home");
        return;
      }
    }
    this._setLovelace();
  }

  private _updateExtraActionItems() {
    const path = this.route?.path?.split("/")[1];

    if (path?.startsWith("areas-")) {
      this._extraActionItems = [
        {
          icon: mdiPencil,
          labelKey: "ui.panel.lovelace.menu.edit_area",
          action: this._editArea,
        },
      ];
    } else if (!path || path === "overview") {
      this._extraActionItems = [
        {
          icon: mdiPencil,
          labelKey: "ui.panel.lovelace.menu.edit_overview",
          action: this._editHome,
        },
      ];
    } else {
      this._extraActionItems = undefined;
    }
  }

  private _editHome = () => {
    showEditHomeDialog(this, {
      config: this._config,
      saveConfig: async (config) => {
        await this._saveConfig(config);
      },
    });
  };

  private _editArea = async () => {
    const path = this.route?.path?.split("/")[1];
    if (!path?.startsWith("areas-")) {
      return;
    }
    const areaId = path.replace("areas-", "");
    const area = this.hass.areas[areaId];
    if (!area) {
      return;
    }
    await this.hass.loadFragmentTranslation("config");
    showAreaRegistryDetailDialog(this, {
      entry: area,
      updateEntry: (values) =>
        updateAreaRegistryEntry(this.hass, areaId, values),
    });
  };

  private _handleLLCustomEvent = (ev: Event) => {
    const detail = (ev as CustomEvent).detail;
    if (detail.home_panel) {
      const { type } = detail.home_panel;
      switch (type) {
        case "assign_area": {
          const { device_id } = detail.home_panel;
          this._showAssignAreaDialog(device_id);
          break;
        }
        case "add_integration": {
          this._showAddIntegrationDialog();
          break;
        }
      }
    }
  };

  private async _showAddIntegrationDialog() {
    await this.hass.loadFragmentTranslation("config");
    showAddIntegrationDialog(this, { navigateToResult: false });
  }

  private _showAssignAreaDialog(deviceId: string) {
    const device = this.hass.devices[deviceId];
    if (!device) {
      return;
    }
    showDeviceRegistryDetailDialog(this, {
      device,
      updateEntry: async (updates) => {
        await updateDeviceRegistryEntry(this.hass, deviceId, updates);
      },
    });
  }

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

    const huiRootStyle = styleMap({
      "--view-container-padding-top": this._bannerHeight.value
        ? `${this._bannerHeight.value}px`
        : undefined,
    });

    return html`
      ${this._renderBanner()}
      <hui-root
        .hass=${this.hass}
        .narrow=${this.narrow}
        .lovelace=${this._lovelace}
        .route=${this.route}
        .panel=${this.panel}
        no-edit
        .extraActionItems=${this._extraActionItems}
        @ll-custom=${this._handleLLCustomEvent}
        style=${huiRootStyle}
      ></hui-root>
    `;
  }

  private _renderBanner() {
    if (!this._showBanner) {
      return nothing;
    }

    return html`
      <div class="banner">
        <div class="banner-content">
          <ha-svg-icon .path=${mdiHomeAssistant}></ha-svg-icon>
          <span class="banner-text">
            ${this.hass.localize("ui.panel.home.banner.welcome_message")}
          </span>
        </div>
        <div class="banner-actions">
          <ha-button size="s" appearance="filled" @click=${this._learnMore}>
            ${this.hass.localize("ui.panel.home.banner.learn_more")}
          </ha-button>
        </div>
      </div>
    `;
  }

  protected updated(changedProps: PropertyValues) {
    super.updated(changedProps);
    if (changedProps.has("_showBanner") || changedProps.has("_lovelace")) {
      if (this._banner) {
        this._bannerHeight.observe(this._banner);
      }
    }
  }

  private _learnMore() {
    showNewOverviewDialog(this, {
      dismiss: async () => {
        const newConfig = {
          ...this._config,
          welcome_banner_dismissed: true,
        };
        this._config = newConfig;
        await saveFrontendSystemData(this.hass.connection, "home", newConfig);
      },
    });
  }

  private get _strategyConfig(): LovelaceDashboardStrategyConfig {
    return {
      strategy: {
        type: "home",
        favorite_entities: this._config.favorite_entities,
        home_panel: true,
        hide_welcome_message: this._config.hide_welcome_message,
        hide_suggested_entities: this._config.hide_suggested_entities,
        shortcuts: this._config.shortcuts,
      },
    };
  }

  private async _setLovelace() {
    if (this._loadConfigPromise) {
      await this._loadConfigPromise;
    }
    const config = await generateLovelaceDashboardStrategy(
      this._strategyConfig,
      this.hass
    );

    this._lovelace = {
      config: config,
      rawConfig: config,
      editMode: false,
      urlPath: "home",
      mode: "generated",
      locale: this.hass.locale,
      enableFullEditMode: () => undefined,
      saveConfig: async () => undefined,
      deleteConfig: async () => undefined,
      setEditMode: () => undefined,
      showToast: () => undefined,
    };
  }

  private async _saveConfig(config: HomeFrontendSystemData): Promise<void> {
    try {
      await saveFrontendSystemData(this.hass.connection, "home", config);
      this._config = config || {};
    } catch (err: any) {
      // eslint-disable-next-line no-console
      console.error("Failed to save home configuration:", err);
      showToast(this, {
        message: this.hass.localize("ui.panel.home.editor.save_failed"),
        duration: 0,
        dismissable: true,
      });
      return;
    }
    showToast(this, {
      message: this.hass.localize("ui.common.successfully_saved"),
    });
    this._setLovelace();
  }

  static readonly styles: CSSResultGroup = css`
    :host {
      display: block;
    }
    .banner {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      padding: var(--ha-space-2) var(--ha-space-4);
      background-color: var(--primary-color);
      color: var(--text-primary-color);
      gap: var(--ha-space-2);
      position: fixed;
      top: var(--header-height, 56px);
      left: var(--ha-sidebar-width, 0px);
      right: 0;
      z-index: 5;
    }
    .banner-content {
      display: flex;
      align-items: center;
      gap: var(--ha-space-2);
      flex: 1;
      min-width: 200px;
    }
    .banner ha-svg-icon {
      --mdc-icon-size: 24px;
      flex-shrink: 0;
    }
    .banner-text {
      font-size: 14px;
      font-weight: 500;
    }
    .banner-actions {
      display: flex;
      flex: none;
      gap: var(--ha-space-2);
      align-items: center;
      margin-inline-start: auto;
    }
    .banner-actions ha-button::part(base) {
      text-wrap: nowrap;
    }
  `;
}

declare global {
  interface HTMLElementTagNameMap {
    "ha-panel-home": PanelHome;
  }
}
