import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
import { ApplicationContext, Action } from '@sankhyalabs/core';
import { S as SnkMessageBuilder } from './SnkMessageBuilder.js';

async function base64ToBlob(base64) {
  const response = await fetch(base64);
  return await response.blob();
}
function buildFileKey(entityName, fieldName) {
  if (entityName) {
    return `${entityName}_${fieldName}`;
  }
  else {
    return fieldName;
  }
}
function hasSpecialCharacters(value) {
  const specialChars = /[ !@#$%^&*()+\-=\[\]{};':"\\|,.<>\/?]/;
  return specialChars.test(value);
}
/**
 * Gera a URL base para upload de sessão
 */
function getSessionUploadBaseUrl(fileKey, context = 'mge') {
  let url = `/${context}/sessionUpload.${context}?sessionkey=${fileKey}`;
  // Verifica se precisa processar caracteres especiais
  if (canProcessSpecialKeys(context) && hasSpecialCharacters(fileKey)) {
    url += `&encodedKey=${btoa(encodeURI(fileKey))}`;
  }
  return url;
}
/**
 * Verifica se pode processar chaves especiais
 * Baseado no método canProcessSpecialKeys do sessionfileupload.service.js
 */
async function canProcessSpecialKeys(context) {
  var _a;
  const application = ApplicationContext.getContextValue("__SNK__APPLICATION__");
  if (!application)
    return false;
  const resourceId = await ((_a = application.getResourceID) === null || _a === void 0 ? void 0 : _a.call(application)) || '';
  const adPrefix = "br.com.sankhya.menu.adicional";
  return context === 'mge' && resourceId.startsWith(adPrefix);
}
/**
 * Constrói a URL de upload
 * Baseado no método buildUploadURL do sessionfileupload.service.js
 */
function buildUploadURL(fileKey) {
  let url = getSessionUploadBaseUrl(fileKey);
  url += "&fitem=S&salvar=S&useCache=N";
  return url;
}
/**
 * Faz upload de arquivo para a sessão usando XMLHttpRequest
 * Baseado no método uploadSessionFile do sessionfileupload.service.js
 */
async function sessionFileUpload(blob, entityName, fieldName, onProgress) {
  const fileKey = buildFileKey(entityName, fieldName);
  const uploadUrl = buildUploadURL(fileKey);
  return new Promise((resolve, reject) => {
    const formData = new FormData();
    formData.append('arquivo', blob);
    const http = new XMLHttpRequest();
    http.addEventListener("load", () => {
      if (http.status >= 200 && http.status < 300) {
        resolve(`/mge/UPLOADING_${fileKey}.dbimage`);
      }
      else {
        reject(new Error(`Upload failed: ${http.statusText}`));
      }
    });
    http.addEventListener("error", () => {
      reject(new Error('Upload error'));
    });
    if (onProgress) {
      http.upload.addEventListener("progress", onProgress);
    }
    http.open("POST", uploadUrl);
    http.send(formData);
  });
}
function getUrlBase() {
  return window.location.origin;
}
function getBaseUrl(pk, entityName, fieldName) {
  if (!pk)
    return undefined;
  const baseUrl = getUrlBase();
  let url = `${baseUrl}/mge/${entityName}@${fieldName}`;
  for (const pkField in pk) {
    url += `@${pkField}=${pk[pkField]}`;
  }
  url += '.dbimage';
  return url;
}
function getPKs(dataUnit) {
  if (!dataUnit) {
    return undefined;
  }
  const pk = {};
  const fields = dataUnit.metadata.fields;
  const selectedRecord = dataUnit.getSelectedRecord();
  fields.forEach((field) => {
    if (field.properties['isPrimaryKey'] && selectedRecord) {
      pk[field.name] = selectedRecord[field.name];
    }
  });
  return pk;
}
async function imageBlobToBase64(blob) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onloadend = () => {
      resolve(reader.result);
    };
    reader.onerror = reject;
    reader.readAsDataURL(blob);
  });
}
async function downloadImage(pks, fieldName, entityName, signal) {
  const uploadUrl = getBaseUrl(pks, entityName, fieldName);
  if (!uploadUrl) {
    return;
  }
  try {
    const response = await fetch(uploadUrl, { signal });
    if (response.ok) {
      const blob = await response.blob();
      return await imageBlobToBase64(blob);
    }
  }
  catch (error) {
    if (signal === null || signal === void 0 ? void 0 : signal.aborted)
      return;
    console.error('Error downloading image:', error);
  }
}

const snkImageInputCss = ":host{display:block}";

const SnkImageInput = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
  constructor() {
    super();
    this.__registerHost();
    this.__attachShadow();
    this.imageError = createEvent(this, "imageError", 7);
    this.dataUnitObserver = async (action) => {
      var _a;
      const actionsMoveSelection = [Action.NEXT_SELECTED, Action.PREVIOUS_SELECTED];
      if (actionsMoveSelection.includes(action.type)) {
        await this.loadImage();
        return;
      }
      const selection = ((_a = action.payload) === null || _a === void 0 ? void 0 : _a.selection) || [];
      if (action.type === Action.SELECTION_CHANGED && selection.length > 0) {
        await this.loadImage();
        return;
      }
      if (action.type === Action.RECORDS_ADDED) {
        await this.clearImage();
        return;
      }
      if (action.type === Action.EDITION_CANCELED) {
        await this.loadImage();
        return;
      }
    };
    this.dataUnit = undefined;
    this.fieldName = undefined;
    this.entityName = undefined;
    this.enabled = true;
    this.acceptType = undefined;
    this.maxSize = undefined;
    this.label = undefined;
    this.imageValue = undefined;
    this.loading = true;
  }
  /**
   * Força o reload da imagem
   */
  async reloadImage(pks) {
    await this.loadImage(pks);
  }
  getMessage(key, params) {
    if (!this.messagesBuilder) {
      this.messagesBuilder = new SnkMessageBuilder();
    }
    return this.messagesBuilder.getMessage(key, params);
  }
  async clearImage() {
    var _a;
    (_a = this._loadAbortController) === null || _a === void 0 ? void 0 : _a.abort();
    this.imageValue = undefined;
  }
  async handleImageChange(event) {
    const base64 = event.detail;
    if (!base64) {
      await this.clearImage();
      await this.updatedataUnitField(true);
      return;
    }
    const blob = await base64ToBlob(base64);
    if (this.maxSize && blob.size > this.maxSize * 1024) {
      const errorMsg = this.getMessage('snkImageInput.errorImageSize') + this.maxSize + '(KB)';
      this.imageError.emit(errorMsg);
      if (this.application) {
        await this.application.error(this.getMessage('snkImageInput.errorTitle'), errorMsg);
      }
      return;
    }
    this.imageValue = base64;
    await sessionFileUpload(blob, this.entityName, this.fieldName);
    await this.updatedataUnitField();
  }
  async updatedataUnitField(deleted = false) {
    if (!this.dataUnit || !this.dataUnit.getSelectedRecord()) {
      return;
    }
    if (deleted) {
      await this.dataUnit.setFieldValue(this.fieldName, 'deletado');
    }
    else {
      await this.dataUnit.setFieldValue(this.fieldName, `$file.session.key{${buildFileKey(this.entityName, this.fieldName)}}`);
    }
  }
  async handleImageError(event) {
    this.imageError.emit(event.detail);
    if (this.application) {
      await this.application.error(this.getMessage('snkImageInput.errorTitle'), event.detail);
    }
  }
  getPksFromDataUnit() {
    if (!this.dataUnit) {
      return undefined;
    }
    const selectedRecord = this.dataUnit.getSelectedRecord();
    if (!selectedRecord) {
      return undefined;
    }
    const fieldValue = selectedRecord[this.fieldName];
    if (!fieldValue) {
      return undefined;
    }
    try {
      const pk = JSON.parse(fieldValue);
      return pk;
    }
    catch (error) {
      console.error('Error parsing PK from data unit field:', error);
      return undefined;
    }
  }
  async loadImage(pks) {
    var _a, _b;
    (_a = this._loadAbortController) === null || _a === void 0 ? void 0 : _a.abort();
    const controller = new AbortController();
    this._loadAbortController = controller;
    this.loading = true;
    if (this.dataUnit && this.entityName) {
      pks = (_b = pks !== null && pks !== void 0 ? pks : this.getPksFromDataUnit()) !== null && _b !== void 0 ? _b : getPKs(this.dataUnit);
      const image = await downloadImage(pks, this.fieldName, this.entityName, controller.signal);
      if (controller.signal.aborted)
        return;
      this.imageValue = image;
    }
    this.loading = false;
  }
  async componentWillLoad() {
    this.application = ApplicationContext.getContextValue("__SNK__APPLICATION__");
    if (!this.messagesBuilder) {
      this.messagesBuilder = new SnkMessageBuilder();
    }
    if (this.dataUnit) {
      this.dataUnit.subscribe(this.dataUnitObserver);
    }
  }
  disconnectedCallback() {
    if (this.dataUnit) {
      this.dataUnit.unsubscribe(this.dataUnitObserver);
    }
  }
  async componentDidLoad() {
    await this.loadImage();
  }
  render() {
    return (h(Host, null, h("ez-image-input", { enabled: this.enabled, label: this.label, name: this.fieldName, value: this.imageValue, maxFileSize: this.maxSize ? this.maxSize * 1024 : undefined, accept: this.acceptType || 'image/png,image/jpeg,image/gif', onEzChange: (e) => this.handleImageChange(e), onEzError: (e) => this.handleImageError(e), loading: this.loading })));
  }
  static get style() { return snkImageInputCss; }
}, [1, "snk-image-input", {
    "dataUnit": [16],
    "fieldName": [1, "field-name"],
    "entityName": [1, "entity-name"],
    "enabled": [4],
    "acceptType": [1, "accept-type"],
    "maxSize": [2, "max-size"],
    "label": [1],
    "imageValue": [32],
    "loading": [32],
    "reloadImage": [64]
  }]);
function defineCustomElement() {
  if (typeof customElements === "undefined") {
    return;
  }
  const components = ["snk-image-input"];
  components.forEach(tagName => { switch (tagName) {
    case "snk-image-input":
      if (!customElements.get(tagName)) {
        customElements.define(tagName, SnkImageInput);
      }
      break;
  } });
}

export { SnkImageInput as S, defineCustomElement as d, getPKs as g };
