/** Dialog for creating/editing a maintenance object. */

import { LitElement, html, css, nothing } from "lit";
import { property, state } from "lit/decorators.js";
import type { HomeAssistant, MaintenanceObject, MaintenanceObjectResponse } from "../types";
import { t, langOf } from "../styles";

import { describeWsError } from "../ws-errors";
import "./ms-textfield";

export class MaintenanceObjectDialog extends LitElement {
  @property({ attribute: false }) public hass!: HomeAssistant;
  /** All objects — choices for the parent-object picker (2.19). */
  @property({ attribute: false }) public objects: MaintenanceObjectResponse[] = [];
  @state() private _open = false;
  @state() private _loading = false;
  @state() private _error = "";
  @state() private _name = "";
  @state() private _manufacturer = "";
  @state() private _model = "";
  @state() private _serialNumber = "";
  @state() private _areaId = "";
  @state() private _installationDate = "";
  // (#67): per-object warranty expiry date
  @state() private _warrantyExpiry = "";
  // v1.4.0 (#43): per-object link to PDF manual / vendor page
  @state() private _documentationUrl = "";
  // v1.4.10 (#46): free-form notes (multiline)
  @state() private _notes = "";
  // 2.19: attach to an existing HA device / nest under another object
  @state() private _haDeviceId = "";
  @state() private _parentEntryId = "";
  @state() private _entryId: string | null = null; // null = create, string = update

  private get _lang(): string {
    return langOf(this.hass);
  }

  public openCreate(): void {
    this._entryId = null;
    this._name = "";
    this._manufacturer = "";
    this._model = "";
    this._serialNumber = "";
    this._areaId = "";
    this._installationDate = "";
    this._warrantyExpiry = "";
    this._documentationUrl = "";
    this._notes = "";
    this._haDeviceId = "";
    this._parentEntryId = "";
    this._error = "";
    this._open = true;
  }

  public openEdit(entryId: string, obj: MaintenanceObject): void {
    this._entryId = entryId;
    this._name = obj.name || "";
    this._manufacturer = obj.manufacturer || "";
    this._model = obj.model || "";
    this._serialNumber = obj.serial_number || "";
    this._areaId = obj.area_id || "";
    this._installationDate = obj.installation_date || "";
    this._warrantyExpiry = obj.warranty_expiry || "";
    this._documentationUrl = obj.documentation_url || "";
    this._notes = obj.notes || "";
    this._haDeviceId = obj.ha_device_id || "";
    this._parentEntryId = obj.parent_entry_id || "";
    this._error = "";
    this._open = true;
  }

  private async _save(): Promise<void> {
    if (this._loading) return;  // synchronous re-entry guard (double-click)
    if (!this._name.trim()) return;
    this._loading = true;
    this._error = "";
    try {
      if (this._entryId) {
        await this.hass.connection.sendMessagePromise({
          type: "maintenance_supporter/object/update",
          entry_id: this._entryId,
          name: this._name,
          manufacturer: this._manufacturer || null,
          model: this._model || null,
          serial_number: this._serialNumber || null,
          area_id: this._areaId || null,
          installation_date: this._installationDate || null,
          warranty_expiry: this._warrantyExpiry || null,
          documentation_url: this._documentationUrl.trim() || null,
          notes: this._notes.trim() || null,
          ha_device_id: this._haDeviceId || null,
          parent_entry_id: this._parentEntryId || null,
        });
      } else {
        await this.hass.connection.sendMessagePromise({
          type: "maintenance_supporter/object/create",
          name: this._name,
          manufacturer: this._manufacturer || null,
          model: this._model || null,
          serial_number: this._serialNumber || null,
          area_id: this._areaId || null,
          installation_date: this._installationDate || null,
          warranty_expiry: this._warrantyExpiry || null,
          documentation_url: this._documentationUrl.trim() || null,
          notes: this._notes.trim() || null,
          ha_device_id: this._haDeviceId || null,
          parent_entry_id: this._parentEntryId || null,
        });
      }
      this._open = false;
      this.dispatchEvent(new CustomEvent("object-saved"));
    } catch (e) {
      this._error = describeWsError(e, this._lang, t("save_error", this._lang));
    } finally {
      this._loading = false;
    }
  }

  private _parentChoices(): MaintenanceObjectResponse[] {
    return (this.objects || []).filter((o) => o.entry_id !== this._entryId);
  }

  private _close(): void {
    this._open = false;
  }

  render() {
    if (!this._open) return html``;
    const L = this._lang;
    const title = this._entryId ? t("edit_object", L) : t("new_object", L);
    return html`
      <ha-dialog open @closed=${this._close}>
        <div class="dialog-title">${title}</div>
        <div class="content">
          ${this._error ? html`<div class="error">${this._error}</div>` : nothing}
          <ms-textfield
            label="${t("name", L)}"
            required
            .value=${this._name}
            @input=${(e: Event) => (this._name = (e.target as HTMLInputElement).value)}
          ></ms-textfield>
          <ms-textfield
            label="${t("manufacturer_optional", L)}"
            .value=${this._manufacturer}
            @input=${(e: Event) => (this._manufacturer = (e.target as HTMLInputElement).value)}
          ></ms-textfield>
          <ms-textfield
            label="${t("model_optional", L)}"
            .value=${this._model}
            @input=${(e: Event) => (this._model = (e.target as HTMLInputElement).value)}
          ></ms-textfield>
          <ms-textfield
            label="${t("serial_number_optional", L)}"
            .value=${this._serialNumber}
            @input=${(e: Event) => (this._serialNumber = (e.target as HTMLInputElement).value)}
          ></ms-textfield>
          <ms-textfield
            label="${t("documentation_url_optional", L)}"
            type="url"
            .value=${this._documentationUrl}
            @input=${(e: Event) => (this._documentationUrl = (e.target as HTMLInputElement).value)}
          ></ms-textfield>
          <ha-area-picker
            .hass=${this.hass}
            label="${t("area_id_optional", L)}"
            .value=${this._areaId}
            @value-changed=${(e: CustomEvent) =>
              (this._areaId = (e.detail.value as string) || "")}
          ></ha-area-picker>
          <ms-textfield
            label="${t("installation_date_optional", L)}"
            type="date"
            .value=${this._installationDate}
            @input=${(e: Event) => (this._installationDate = (e.target as HTMLInputElement).value)}
          ></ms-textfield>
          <ms-textfield
            label="${t("warranty_expiry_optional", L)}"
            type="date"
            .value=${this._warrantyExpiry}
            @input=${(e: Event) => (this._warrantyExpiry = (e.target as HTMLInputElement).value)}
          ></ms-textfield>
          <ha-form
            .hass=${this.hass}
            .data=${{ device: this._haDeviceId || undefined }}
            .schema=${[{ name: "device", selector: { device: {} } }]}
            .computeLabel=${() => t("link_device_optional", L)}
            @value-changed=${(e: CustomEvent) =>
              (this._haDeviceId =
                ((e.detail.value as { device?: string })?.device as string) || "")}
          ></ha-form>
          ${this._parentChoices().length
            ? html`<label class="textarea-field">
                <span class="textarea-label">${t("parent_object_optional", L)}</span>
                <select
                  class="parent-select"
                  .value=${this._parentEntryId}
                  @change=${(e: Event) =>
                    (this._parentEntryId = (e.target as HTMLSelectElement).value)}
                >
                  <option value="" ?selected=${!this._parentEntryId}>
                    ${t("parent_none", L)}
                  </option>
                  ${this._parentChoices().map(
                    (o) => html`<option
                      value=${o.entry_id}
                      ?selected=${this._parentEntryId === o.entry_id}
                    >${o.object.name}</option>`,
                  )}
                </select>
              </label>`
            : nothing}
          <label class="textarea-field">
            <span class="textarea-label">${t("object_notes_optional", L)}</span>
            <textarea
              rows="3"
              .value=${this._notes}
              @input=${(e: Event) => (this._notes = (e.target as HTMLTextAreaElement).value)}
            ></textarea>
          </label>
        </div>
        <div class="dialog-actions">
          <ha-button appearance="plain" @click=${this._close}>
            ${t("cancel", this._lang)}
          </ha-button>
          <ha-button
            @click=${this._save}
            .disabled=${this._loading || !this._name.trim()}
          >
            ${this._loading ? t("saving", this._lang) : t("save", this._lang)}
          </ha-button>
        </div>
      </ha-dialog>
    `;
  }

  static styles = css`
    .dialog-title {
      font-size: 18px;
      font-weight: 500;
      padding-bottom: 12px;
    }
    .content {
      display: flex;
      flex-direction: column;
      gap: 16px;
      min-width: 300px;
    }
    .dialog-actions {
      display: flex;
      justify-content: flex-end;
      gap: 8px;
      padding-top: 16px;
    }
    ms-textfield {
      display: block;
    }
    .textarea-field {
      display: flex; flex-direction: column; gap: 4px;
    }
    .textarea-label {
      font-size: 12px; color: var(--secondary-text-color, #888); font-weight: 500;
    }
    .textarea-field textarea {
      padding: 8px 10px; font-size: 14px; font-family: inherit;
      background: var(--secondary-background-color, rgba(0,0,0,0.06));
      color: var(--primary-text-color);
      border: 1px solid var(--divider-color); border-radius: 6px;
      resize: vertical;
    }
    .textarea-field textarea:focus {
      outline: none; border-color: var(--primary-color);
    }
    .parent-select {
      padding: 8px 10px; font-size: 14px; font-family: inherit;
      background: var(--secondary-background-color, rgba(0,0,0,0.06));
      color: var(--primary-text-color);
      border: 1px solid var(--divider-color); border-radius: 6px;
    }
    .error {
      color: var(--error-color, #f44336);
      font-size: 13px;
    }
  `;
}

if (!customElements.get("maintenance-object-dialog")) {
  customElements.define("maintenance-object-dialog", MaintenanceObjectDialog);
}
