import {
  PCN_PUT_VIDEO,
  VIDEO_ADMIN,
  VIDEO_ADVANCED_TAB,
  VIDEO_EDIT_SOURCE,
  VIDEO_INFO_TAB,
  VIDEO_SHOW_CONTENT_OWNER_NAME,
  VIDEO_VERSION_UPLOAD,
} from '@/modules/@common/acl/constants';
import { INTERNAL } from '@/modules/@common/user/constants/rolesType';
import { VIDEO_STATE_PROCESSING } from '@/modules/editorial/editorialSearch/constants/searchFilter';
import { FEED_TYPE_AUDIO } from '@/modules/editorial/editorialSearchFilter/constants';
import {
  ACCESS_LEVEL_ENUM,
  ACCESS_USER_ROLE,
} from '@/modules/editorial/editorialSearchResults/components/AccessControlView/constants';

import { slice } from '../redux/slices';
import { iabFindLeafNodes } from '@/modules/@common/iab/helpers';
import { getUserPreferences, hasPermission, isOwnContent, setUserPreferences } from '@/modules/@common/user/helpers';

const nameSpace = slice.name;

export const canShowVideoContentOwnerName = (userPermissions) =>
  hasPermission(VIDEO_SHOW_CONTENT_OWNER_NAME, userPermissions);

export const canEditVideoByAccessControl = (video, userPublisherIds, userId) => {
  if (video?.access?.level === ACCESS_LEVEL_ENUM.private && video?.access?.users) {
    return video.access.users.some((user) => +user.id === userId && user.role === ACCESS_USER_ROLE.owner);
  }

  if (video?.access?.level === ACCESS_LEVEL_ENUM.site) {
    const videoSites = (video.access.sites || []).map((s) => parseInt(s.id, 10));

    return (userPublisherIds || []).some((userSite) => videoSites.some((videoSite) => videoSite === userSite));
  }

  return true;
};

export const getContentOwnerNameAndFeedDisplayName = (video, userContentOwners, userPermissions) =>
  [
    canShowVideoContentOwnerName(userPermissions) && video?.contentOwnerName,
    video?.feedDescription || (isOwnContent(video?.contentOwner, userContentOwners) ? 'My Videos' : 'AnyClip'),
  ]
    .filter(Boolean)
    .join('/');

export const tagsGenerator = (video, searchFilters) => {
  const relevantCategories = ['brands', 'people', 'categories'];
  const tagFilters =
    (searchFilters &&
      Object.entries(searchFilters).reduce(
        (acc, [key, { filters }]) =>
          relevantCategories.includes(key) ? { ...acc, [key]: filters[0].value.map(({ value }) => value) } : acc,
        {},
      )) ||
    {};

  const keywords = [...(video?.keywords ?? [])];

  const iab = video?.iab?.data ? iabFindLeafNodes(JSON.parse(video.iab.data)) : [];

  const tagsMap = {
    people: [],
    brands: [],
    iab: [],
    brandsafety: [],
    keywords: [],
    text: [],
    custom: [],
  };

  keywords.forEach((elem) => {
    const type = elem.category.toLowerCase().replace(/_/, '');

    if (tagsMap[type]) {
      const tagEntity = {
        type,
        text: elem.value,
        filterMatch: tagFilters[type]?.includes(elem.value),
        id: ['text', 'custom'].includes(type) ? elem.value : elem.id,
      };

      if (type === 'custom') {
        tagEntity.labelId = elem.labelId;
        tagEntity.labelName = elem.labelName;
        tagEntity.color = elem.color;
      }

      tagsMap[type].push(tagEntity);
    }
  });

  iab.forEach((elem) => {
    try {
      return tagsMap.iab.push({
        type: 'iab',
        text: elem.name,
        id: elem.id,
        filterMatch: tagFilters.categories?.includes(elem.id),
      });
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
    } catch (err) {
      return null;
    }
  });

  return Object.keys(tagsMap).reduce((acc, key) => [...acc, ...tagsMap[key]], []);
};

export const defineThumbnail = (thumbnailUrl, thumbnailFiles) => {
  if (thumbnailFiles?.length) {
    const sortedThumbnails = [...thumbnailFiles].sort((a, b) => b.height - a.height);
    const thumbnailHighResolution = sortedThumbnails[0];
    return thumbnailHighResolution && thumbnailHighResolution.file ? thumbnailHighResolution.file : thumbnailUrl;
  }

  return thumbnailUrl;
};

export const formatBytes = (bytes, decimals = 2) => {
  if (bytes === 0) return '0 Bytes';

  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];

  const i = Math.floor(Math.log(bytes) / Math.log(k));

  return `${parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
};

export const getPreferences = () => getUserPreferences()?.[nameSpace];

export const setPreferences = (param, value) => {
  const preferences = getPreferences();
  setUserPreferences(nameSpace, { ...preferences, [param]: value });
};

export const canPermissionAccess = (
  video,
  permissionGrandAccessName,
  permissionContentOwnerAccessName,
  userContentOwners,
  userPermissions,
) => {
  const { contentOwner, status } = video;

  if (status === VIDEO_STATE_PROCESSING) return false;
  if (hasPermission(permissionGrandAccessName, userPermissions)) return true;

  return (
    permissionContentOwnerAccessName &&
    hasPermission(permissionContentOwnerAccessName, userPermissions) &&
    isOwnContent(contentOwner, userContentOwners)
  );
};

export const canAccessTabInfo = (video, userContentOwners, userPermissions) =>
  canPermissionAccess(video, VIDEO_ADMIN, VIDEO_INFO_TAB, userContentOwners, userPermissions);
export const canAccessTabAdvanced = (video, userContentOwners, userPermissions) =>
  canPermissionAccess(video, VIDEO_ADVANCED_TAB, null, userContentOwners, userPermissions);
export const canArchive = (video, userContentOwners, userPermissions) =>
  canPermissionAccess(video, VIDEO_ADMIN, PCN_PUT_VIDEO, userContentOwners, userPermissions);

export const speechModelTypes = {
  google: 'S2T',
  deepgram: 'DEEPGRAM_ANYCLIP',
  verbitAuto: 'VERBIT_AUTO',
  verbitManual: 'VERBIT_MANUAL',
  verbitManual24h: 'VERBIT_MANUAL_24H',
};

export const getCanEditVideoAttributes = (
  video,
  userAccountId,
  userPublisherIds,
  userId,
  userContentOwners,
  userPermissions,
  userRoleType,
) => {
  const hasAccount = !!userAccountId;
  const hasOwnContent = !!(video?.contentOwner && isOwnContent(video?.contentOwner, userContentOwners));
  const canEditByAccessControlRules = canEditVideoByAccessControl(video, userPublisherIds, userId);

  const canEditByPermissions = (permission) =>
    hasPermission(permission, userPermissions) &&
    canEditByAccessControlRules &&
    (!hasAccount || hasOwnContent) &&
    video.status !== VIDEO_STATE_PROCESSING;

  const canEditByAccessControlAndOwnContent = () =>
    canEditByAccessControlRules && hasOwnContent && video.status !== VIDEO_STATE_PROCESSING;

  const canEditSyndicatedVideo = () =>
    video?.access?.level === ACCESS_LEVEL_ENUM.public && hasPermission(VIDEO_ADMIN, userPermissions);

  const canOperateWithVideoVersionUpload = () =>
    hasPermission(VIDEO_VERSION_UPLOAD, userPermissions) &&
    canEditByAccessControlRules &&
    video?.access?.level !== ACCESS_LEVEL_ENUM.public &&
    video.origin !== FEED_TYPE_AUDIO;

  const attributes = {
    canEditVideoName: canEditByPermissions(PCN_PUT_VIDEO),
    canEditVideoDate: canEditByPermissions(PCN_PUT_VIDEO),
    canEditVideoDescription: canEditByPermissions(PCN_PUT_VIDEO),
    canEditVideoSource: canEditByPermissions(VIDEO_EDIT_SOURCE),
    canEditTagsAndLabels: canEditByAccessControlAndOwnContent() || canEditSyndicatedVideo(),
    canSeeMenu: canEditByAccessControlAndOwnContent() || canEditSyndicatedVideo(),
    // used in ShareAndAccess
    canEditVideo: canEditByAccessControlAndOwnContent() || canEditSyndicatedVideo(),
    canOperateWithVideoVersionUpload: canOperateWithVideoVersionUpload(),
    canShowTabVideoVersions: canOperateWithVideoVersionUpload() || userRoleType === INTERNAL,
  };

  return attributes;
};

export const enableTagLogByQueryParam = () => {
  const paramName = 'taglog';
  return typeof window !== 'undefined' && window.location.search.includes(paramName);
};
