// retoor <retoor@molodetz.nl>

import { Component } from "./Component.js";
import { assetUrl } from "../assetVersion.js";

const CSS_ID = "ai-field-css";
const EUROPEAN_DATE = /^(\d{1,2})[./-](\d{1,2})[./-](\d{4})$/;
const ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})$/;

function toEuropeanDate(value) {
  const text = String(value || "").trim();
  if (!text) return "";
  const iso = text.match(ISO_DATE);
  if (iso) return `${iso[3]}/${iso[2]}/${iso[1]}`;
  const eu = text.match(EUROPEAN_DATE);
  if (eu) {
    const day = eu[1].padStart(2, "0");
    const month = eu[2].padStart(2, "0");
    return `${day}/${month}/${eu[3]}`;
  }
  return text;
}

function parseEuropeanDate(value) {
  const text = String(value || "").trim();
  if (!text) return null;
  let day;
  let month;
  let year;
  const iso = text.match(ISO_DATE);
  if (iso) {
    year = Number(iso[1]);
    month = Number(iso[2]);
    day = Number(iso[3]);
  } else {
    const eu = text.match(EUROPEAN_DATE);
    if (!eu) return null;
    day = Number(eu[1]);
    month = Number(eu[2]);
    year = Number(eu[3]);
  }
  if (month < 1 || month > 12 || day < 1 || day > 31) return null;
  const date = new Date(Date.UTC(year, month - 1, day));
  if (
    date.getUTCFullYear() !== year ||
    date.getUTCMonth() !== month - 1 ||
    date.getUTCDate() !== day
  ) {
    return null;
  }
  const dd = String(day).padStart(2, "0");
  const mm = String(month).padStart(2, "0");
  return {
    european: `${dd}/${mm}/${year}`,
    iso: `${year}-${mm}-${dd}`,
  };
}

export class AiField extends Component {
  static get observedAttributes() {
    return [
      "name",
      "type",
      "label",
      "help",
      "placeholder",
      "min",
      "max",
      "step",
      "maxlength",
      "pattern",
      "required",
      "disabled",
      "value",
    ];
  }

  _ensureCss() {
    if (document.getElementById(CSS_ID)) return;
    const link = document.createElement("link");
    link.id = CSS_ID;
    link.rel = "stylesheet";
    link.href = assetUrl("/static/css/components/ai-field.css");
    document.head.appendChild(link);
  }

  connectedCallback() {
    this._ensureCss();
    if (this._built) return;
    this._built = true;
    this.classList.add("ai-field");
    const type = this.attr("type", "text");
    this._fieldType = type;
    const name = this.attr("name", "field");
    const label = this.attr("label", name);
    const wrap = document.createElement("label");
    wrap.className = "ai-field-wrap";
    const title = document.createElement("span");
    title.className = "ai-widget-label";
    title.textContent = label;
    wrap.appendChild(title);
    const helpText =
      this.attr("help") ||
      (type === "date" ? "Format: DD/MM/YYYY" : "");
    if (helpText) {
      const help = document.createElement("span");
      help.className = "ai-widget-help";
      help.textContent = helpText;
      wrap.appendChild(help);
    }
    const input = document.createElement("input");
    input.className = "ai-field-input";
    input.name = name;
    if (type === "number") {
      input.type = "number";
    } else {
      input.type = "text";
    }
    if (type === "date") {
      input.inputMode = "numeric";
      input.autocomplete = "off";
      input.placeholder = this.attr("placeholder", "DD/MM/YYYY");
      input.maxLength = 10;
      input.pattern = "\\d{1,2}[/.-]\\d{1,2}[/.-]\\d{4}";
      input.title = "DD/MM/YYYY";
      input.value = toEuropeanDate(this.attr("value", ""));
    } else {
      input.placeholder = this.attr("placeholder", "");
      input.value = this.attr("value", "");
    }
    if (this.hasAttribute("min") && type === "number") input.min = this.attr("min");
    if (this.hasAttribute("max") && type === "number") input.max = this.attr("max");
    if (this.hasAttribute("step") && type === "number") input.step = this.attr("step");
    if (this.hasAttribute("maxlength") && type !== "date") {
      input.maxLength = this.intAttr("maxlength", 0) || 524288;
    }
    if (this.attr("pattern") && type !== "date") input.pattern = this.attr("pattern");
    if (this.boolAttr("required")) input.required = true;
    if (this.boolAttr("disabled")) input.disabled = true;
    input.addEventListener("input", () => {
      if (this._fieldType === "date") {
        const cleaned = input.value.replace(/[^\d/.\-]/g, "").slice(0, 10);
        if (cleaned !== input.value) input.value = cleaned;
      }
      this.dispatchEvent(
        new CustomEvent("ai:change", {
          bubbles: true,
          composed: true,
          detail: { name, value: this.getValue() },
        })
      );
    });
    input.addEventListener("blur", () => {
      if (this._fieldType !== "date") return;
      const parsed = parseEuropeanDate(input.value);
      if (parsed) input.value = parsed.european;
    });
    wrap.appendChild(input);
    this.innerHTML = "";
    this.appendChild(wrap);
    this._input = input;
  }

  getValue() {
    if (!this._input) return this.attr("value", "");
    if (this._fieldType === "number" || this._input.type === "number") {
      const n = this._input.valueAsNumber;
      return Number.isNaN(n) ? null : n;
    }
    if (this._fieldType === "date") {
      const parsed = parseEuropeanDate(this._input.value);
      return parsed ? parsed.european : this._input.value.trim();
    }
    return this._input.value;
  }

  validate() {
    if (!this._input) return { valid: true };
    if (this._fieldType === "date") {
      const raw = this._input.value.trim();
      if (!raw) {
        if (this.boolAttr("required")) {
          return { valid: false, message: "Enter a date as DD/MM/YYYY" };
        }
        return { valid: true };
      }
      if (!parseEuropeanDate(raw)) {
        return { valid: false, message: "Date must be DD/MM/YYYY" };
      }
      return { valid: true };
    }
    if (!this._input.checkValidity()) {
      return { valid: false, message: this._input.validationMessage || "Invalid value" };
    }
    return { valid: true };
  }

  focus() {
    if (this._input) this._input.focus();
  }
}

if (!customElements.get("ai-field")) {
  customElements.define("ai-field", AiField);
}

export default AiField;
