import { createAssetView } from '../asset_manager';

export const ASSET_PRESIGN_TTL_MS = 240 * 1000; // backend issues 5 min tokens; refresh slightly early
export const DEFAULT_FOLDER_NAME = 'Documents';
export const DEFAULT_SORT_FIELD = 'title';
export const DEFAULT_SORT_DIRECTION = 'asc';
export const SORT_FIELD_VALUES = ['title', 'issued_at', 'created_at', 'updated_at'];
export const TAG_FILTER_UNTAGGED = '__UNTAGGED__';

const ROW_KEY_SEPARATOR = ':';
const DOCUMENT_ROW_PREFIX = 'document';
const FOLDER_ROW_PREFIX = 'folder';

export const resolveApiPath = (path = '') => path;

const makeRowKey = (type, id) =>
  id ? `${type}${ROW_KEY_SEPARATOR}${id}` : `${type}${ROW_KEY_SEPARATOR}`;

const getRowType = (key) => (
  typeof key?.split === 'function' ? key.split(ROW_KEY_SEPARATOR, 1)[0] : ''
);

export const getRowId = (key) => {
  if (typeof key?.indexOf !== 'function' || typeof key?.slice !== 'function') return '';
  const separatorIndex = key.indexOf(ROW_KEY_SEPARATOR);
  if (separatorIndex === -1) return key;
  return key.slice(separatorIndex + 1);
};

export const isDocumentRowKey = (key) => getRowType(key) === DOCUMENT_ROW_PREFIX;
export const isFolderRowKey = (key) => getRowType(key) === FOLDER_ROW_PREFIX;

export const resolveDocumentRowKey = (documentId) =>
  documentId ? makeRowKey(DOCUMENT_ROW_PREFIX, documentId) : null;

export const resolveFolderRowKey = (folderId) =>
  folderId ? makeRowKey(FOLDER_ROW_PREFIX, folderId) : null;

export const hasFiles = (event) =>
  Array.from(event.dataTransfer?.types || []).includes('Files');

const isAssetEquivalent = (lhs, rhs) => {
  if (!lhs || !rhs) return false;
  const lhsView = createAssetView(lhs);
  const rhsView = createAssetView(rhs);
  const lhsPrimaryMetadata = lhsView.getPrimaryMetadata() || lhs?.metadata;
  const rhsPrimaryMetadata = rhsView.getPrimaryMetadata() || rhs?.metadata;
  const lhsCardinality = lhsView.getCardinality() || lhs?.cardinality || null;
  const rhsCardinality = rhsView.getCardinality() || rhs?.cardinality || null;
  const lhsObjects = lhsView.getObjects();
  const rhsObjects = rhsView.getObjects();
  const objectsComparable =
    lhsObjects.length === rhsObjects.length
    && lhsObjects.every((entry, index) => {
      const other = rhsObjects[index];
      if (!other) return false;
      if (entry.ordinal !== other.ordinal) return false;
      if (entry.url && other.url && entry.url === other.url) {
        return true;
      }
      if (!entry.url && !other.url) {
        return JSON.stringify(entry.metadata || null) === JSON.stringify(other.metadata || null);
      }
      return entry.url === other.url;
    });
  return (
    lhs.id === rhs.id
    && lhs.url === rhs.url
    && lhsPrimaryMetadata?.width === rhsPrimaryMetadata?.width
    && lhsPrimaryMetadata?.height === rhsPrimaryMetadata?.height
    && lhs.mime_type === rhs.mime_type
    && lhs.asset_type === rhs.asset_type
    && lhs.updated_at === rhs.updated_at
    && lhsCardinality === rhsCardinality
    && objectsComparable
  );
};

const mergeAssetIntoGroup = (group, assetData) => {
  if (!assetData || !assetData.asset_type) {
    if (Array.isArray(group)) {
      return group;
    }
    return group || {};
  }

  if (Array.isArray(group) || !group) {
    const list = Array.isArray(group) ? group : [];
    const index = list.findIndex((item) => item?.id === assetData.id);
    if (index >= 0) {
      const existing = list[index];
      if (isAssetEquivalent(existing, assetData)) {
        return list;
      }
      const next = list.slice();
      next[index] = { ...existing, ...assetData };
      return next;
    }
    return list.concat({ ...assetData });
  }

  const key = assetData.asset_type;
  const previous = group?.[key];
  if (previous && isAssetEquivalent(previous, assetData)) {
    return group;
  }

  const next = { ...(group || {}) };
  next[key] = { ...(previous || {}), ...assetData };
  return next;
};

export const mergeAssetIntoDocument = (doc, assetData) => {
  if (!doc) return doc;
  const existingGroup = doc.current_version?.assets || null;
  const nextGroup = mergeAssetIntoGroup(existingGroup, assetData);
  if (nextGroup === existingGroup) {
    return doc;
  }
  const updatedCurrentVersion = doc.current_version
    ? { ...doc.current_version, assets: nextGroup }
    : { assets: nextGroup };
  return { ...doc, current_version: updatedCurrentVersion };
};

export const createRootNode = () => ({
  id: 'root',
  name: DEFAULT_FOLDER_NAME,
  parentId: null,
  children: [],
  expanded: true,
  loaded: false,
  hasChildren: false,
});
