'use strict';

angular.module('angularJSApp.linkViewDownload', []).controller('ViewDownloadCtrl', [
  '$scope',
  '$state',
  'ngToast',
  '$http',
  'Util',
  'configServer',
  '$cookies',
  'session',
  'Patterns',
  '$stateParams',
  '$timeout',
  'AppUtil',
  '$translate',
  'AppConfig',
  'ViewerUrl',
  'ViewerSupportType',
  '$sce',
  '$uibModal',
  '$rootScope',
  'moment',
  '$window',
  '$q',
  function (
    $scope,
    $state,
    ngToast,
    $http,
    Util,
    configServer,
    $cookies,
    session,
    Patterns,
    $stateParams,
    $timeout,
    AppUtil,
    $translate,
    AppConfig,
    ViewerUrl,
    ViewerSupportType,
    $sce,
    $uibModal,
    $rootScope,
    moment,
    $window,
    $q
  ) {
    $scope.Patterns = Patterns;
    $scope.linkAuthen = {
      email: '',
      pin: '',
    };
    $scope.folderPathId = '';
    $scope.stk = '';
    $scope.reply = {
      subject: '',
      message: '',
    };
    $scope.listFileSuccess = [];

    $scope.language = session.getCurrentLanguage();
    $scope.loading = true;
    $scope.link = {};
    $scope.error = false;
    $scope.errMessage = '';
    var recheckZipStatus = undefined;
    $scope.listQueueDownload = [];
    $scope.listFile = [];
    $scope.isSelected = false;
    $scope.selectedAll = false;
    $scope.isShowFullMoreInfoContent = false;
    $scope.listReplyFile = [];
    $scope.script_pattern = Patterns.SCRIPT_PATTERN;

    $scope.verifyLinkEmail = function (valid, showSuccess) {
      if (!valid) return;
      //Verify email access link
      Util.createRequest(
        configServer.API_URL + '/links/' + $stateParams.link_id + '/access',
        'POST',
        {
          email: $scope.linkAuthen.email,
          language: $scope.language,
        },
        function (res) {
          if (res.status === 200) {
            $scope.accessKey = res.description;
            $scope.link.verified = 2;
            if (showSuccess === true) {
              Util.createToast({
                className: 'success',
                content: 'VIEW_DOWNLOAD.RESEND_SUCCESS',
              });
            }
          } else if (res.status === 403) {
            Util.createToast({
              className: 'danger',
              content: 'VIEW_DOWNLOAD.LINK_INVALID_EMAIL',
            });
          } else {
            Util.createToast({
              className: 'danger',
              content: 'SERVER_ERROR.' + res.status,
            });
          }
        },
        function (err) {}
      );
    };

    $scope.checkSupportViewOnline = function (file) {
      var fileExt = getExtension(file.name);
      fileExt && (fileExt = fileExt.toLowerCase());
      if (
        ViewerSupportType.SUPPORT_TYPES_DOC.indexOf(fileExt) !== -1 &&
        file.key_id &&
        file.view_content_id
      ) {
        return true;
      } else {
        return false;
      }
    };

    $scope.verifyPINCode = function (valid) {
      $scope.isShowButton = true;
      if (!valid) return;

      //Verify email access link PIN
      Util.createRequest(
        configServer.API_URL + '/links/' + $stateParams.link_id + '/access',
        'GET',
        {
          pin_code: window.btoa($scope.linkAuthen.pin),
        },
        function (res) {
          if (res.status === 200) {
            //get list link item
            $scope.stk = res.data.session_id;
            getLinkAPI();
          } else {
            Util.createToast({
              className: 'danger',
              content: 'SERVER_ERROR.' + res.status,
            });
            $scope.isShowButton = false;
          }
        },
        function (err) {}
      );
    };

    // Do get link
    function getLinkAPI(cb, error) {
      //Verify email access link PIN
      Util.createRequest(
        configServer.API_URL + '/links/' + $stateParams.link_id + '/items',
        'GET',
        {
          project_id: $stateParams.project_id,
          access_key: $scope.accessKey,
        },
        function (res) {
          if (res.status === 200) {
            $scope.link.verified = 3;
            $scope.listFile = res.data;
            $scope.filterFilesEncoded = _.filter($scope.listFile, function (file) {
              return file.is_encrypt === 1;
            });
            if ($scope.filterFilesEncoded.length > 0) {
              $scope.isShowFullMoreInfoContent = true;
            }

            $scope.loading = false;
            cb && cb(res);
          } else {
            $translate(['SERVER_ERROR.' + res.status]).then(function (translations) {
              $scope.errMessage = translations['SERVER_ERROR.' + res.status];
            });
            $scope.error = true;
          }
        },
        function (err) {}
      );
    }

    //Convert file size
    $scope.convertFileSize = function (size) {
      return Util.convertFileSize(size);
    };

    // Get group from mime type
    $scope.getGroupFromMimeType = function (file) {
      return Util.getGroupFromMimeType(file);
    };

    function getLinkInfo(cb) {
      Util.createRequest(
        configServer.API_URL + '/links/' + $stateParams.link_id,
        'GET',
        { project_id: $stateParams.project_id },
        function (res) {
          if (res.status === 200) {
            $scope.link = res.data;
            $scope.linkExpireDate = $scope.formatCompareDate(res.data.expiry_date);
            if ($scope.link.status === 1 && $scope.link.link_use_type === 2) {
              $scope.link.verified = 1;
            }
            cb && cb();
          } else {
            $translate(['SERVER_ERROR.' + res.status]).then(function (translations) {
              $scope.errMessage = translations['SERVER_ERROR.' + res.status];
            });
            $scope.error = true;
          }
          $scope.loading = false;
        },
        function (err) {
          $scope.loading = false;
        }
      );
    }

    $scope.formatCompareDate = function (date) {
      return moment(date).format(AppConfig.MAX_EXPIRY_DATE_FORMAT);
    };

    // innit
    getLinkInfo(function () {
      var recheckLinkStatus = setInterval(function () {
        if ($scope.link.status === 3) {
          getLinkInfo();
        } else {
          clearInterval(recheckLinkStatus);
        }
      }, 3000);
    });

    $scope.toggleSelectAll = function () {
      $scope.selectedAll = !$scope.selectedAll;
      _.forEach($scope.listFile, function (item) {
        item._selected = $scope.selectedAll;
      });
      $scope.isSelected = $scope.selectedAll;
    };

    $scope.toggleSelected = function (obj) {
      if (angular.isObject(obj) && obj.id) {
        obj._selected ? (obj._selected = false) : (obj._selected = true);
      }
      var selectedItems = _.filter($scope.listFile, function (item) {
        return item._selected;
      });
      $scope.selectedAll = selectedItems.length === $scope.listFile.length;
      $scope.isSelected = selectedItems.length > 0;
    };

    //download selected when isSelected is true
    $scope.downloadSelected = function (isSelected) {
      if (!$scope.link.allowed_download_file) return;

      var selectedFileIds = isSelected
        ? _.filter($scope.listFile, function (item) {
            return item._selected;
          })
        : $scope.listFile;
      if (selectedFileIds.length === 0) return;

      if ($scope.link.password_protect_download) {
        //filter in list selected:  list encode && list non-encode
        var selectedEncryptedFileIds = _.filter(selectedFileIds, function (item) {
          return item.is_encrypt === 1;
        });
        var selectedNoneEncryptedFileIds = _.filter(selectedFileIds, function (item) {
          return item.is_encrypt !== 1;
        });

        //download for encrypted file
        if (selectedEncryptedFileIds.length > 0) {
          _.forEach(selectedEncryptedFileIds, function (file) {
            $scope.downloadSingleFile(file.id, file.name);
          });
        }
        //down zip files
        if (selectedNoneEncryptedFileIds.length > 0) {
          var fileIdArr = selectedNoneEncryptedFileIds.map(function (file) {
            return file.id;
          });
          var fileIds = _.join(fileIdArr, ',');

          prepareZip(fileIds);
        }
      } else {
        _.forEach(selectedFileIds, function (file) {
          $scope.downloadSingleFile(file.id, file.name);
        });
      }
    };

    // preparing for zip queue
    function prepareZip(fileIds) {
      openModalDownloadZip();
      var params = {
        project_id: $stateParams.project_id,
        link_id: $stateParams.link_id,
        lang: $scope.language,
        email: window.btoa($scope.linkAuthen.email),
        file_ids: fileIds,
        access_key_id: $scope.accessKey,
      };
      Util.createRequest(
        configServer.API_URL + '/download/files/zip',
        'GET',
        params,
        function (res) {
          if (res.status === 200) {
            $scope.listQueueDownload.push(res.data.queue_id);
            if (recheckZipStatus === undefined) {
              recheckZipStatus = setInterval(function () {
                if ($scope.listQueueDownload.length > 0) {
                  checkPrepareZipStatus($scope.listQueueDownload[0]);
                } else {
                  clearInterval(recheckZipStatus);
                  recheckZipStatus = undefined;
                }
              }, 4000);
            }

            // checkPrepareZipStatus(res.data.queue_id);
          } else {
            Util.createToast({
              className: 'danger',
              content: 'DOWNLOAD_ERR',
            });
            $rootScope.$broadcast('close_modal');
          }
        },
        function (err) {
          $translate(['SERVER_ERROR.' + err.status]).then(function (translations) {
            $scope.errMessage = translations['SERVER_ERROR.' + err.status];
          });
          $scope.error = true;
          $rootScope.$broadcast('close_modal');
        }
      );
    }

    //check preparing zip status
    function checkPrepareZipStatus(queueId) {
      Util.createRequest(
        configServer.API_URL + '/download/folders/status',
        'GET',
        { queue_id: queueId },
        function (res) {
          if (res.status === 200) {
            if (res.data.status === 3) {
              $scope.listQueueDownload.splice(0, 1);
              downloadZip(queueId);
              $rootScope.$broadcast('close_modal');
            } else if (res.data.status === 4) {
              $scope.listQueueDownload.splice(0, 1);
            }
          } else {
            $translate(['SERVER_ERROR.' + res.status]).then(function (translations) {
              $scope.errMessage = translations['SERVER_ERROR.' + res.status];
            });
            $scope.error = true;
            $rootScope.$broadcast('close_modal');
          }
        },
        function (err) {
          $translate(['SERVER_ERROR.' + err.status]).then(function (translations) {
            $scope.errMessage = translations['SERVER_ERROR.' + err.status];
          });
          $scope.error = true;
          $rootScope.$broadcast('close_modal');
        }
      );
    }

    // do download zip queue
    function downloadZip(queueId) {
      var url = configServer.API_URL + '/download/folders/queue/' + queueId;
      $.fileDownload(url, { httpMethod: 'GET' })
        .done(function () {
          // Success download
        })
        .fail(function () {
          //If the browser is not iE or Edge => shows an error
          if (detectBrowsers() === false) {
            Util.createToast({
              className: 'danger',
              content: 'DOWNLOAD_ERR',
            });
          }
        });
    }

    $scope.downloadFileId = function (file) {
      if (!$scope.link.allowed_download_file) return;
      // Check if the file is a ZIP file
      var isZipFile = (file.content_type && file.content_type.toLowerCase().endsWith('zip')) ||
                      (file.name && (file.name.toLowerCase().endsWith('.zip') || file.name.toLowerCase().endsWith('.zip.enc')));

      if ($scope.link.password_protect_download) {
        if (isZipFile && file.is_encrypt === 1) {
          openModalDownloadOrUnzipAndSaveFolder(file);
        } else {
          file.is_encrypt === 1 ? $scope.downloadSingleFile(file.id, file.name) : prepareZip(file.id);
        }
      } else {
        if (isZipFile) {
          // Check if the file is a ZIP file and show modal for download or unzip
          openModalDownloadOrUnzipAndSaveFolder(file);
        } else {
          // Check if the file is not a ZIP file and download it
          $scope.downloadSingleFile(file.id, file.name);
        }
      }
    };

    $scope.downloadSingleFile = async function (
      fileId,
      name,
      isUnzipFile = false,
      dirHandle = null
    ) {
      var data = {
        email: $scope.linkAuthen.email,
        os: '',
      };
      var myJSON = JSON.stringify(data);
      var encodedString = window.btoa(myJSON.toString());

      var fileItem = _.find($scope.listFile, { id: fileId });
      // Check if it is a ZIP file by extension, content type, or if unzip flow is explicitly requested
      var isZipFile =
        (name && (name.toLowerCase().endsWith('.zip') || name.toLowerCase().endsWith('.zip.enc'))) ||
        (fileItem &&
          fileItem.content_type &&
          fileItem.content_type.toLowerCase().endsWith('zip')) ||
        isUnzipFile;


      var type = 1;
      // var type = (asZip) ? 3 : 1;
      var url = configServer.API_URL + '/download/files/' + fileId + '/share';
      url +=
        '?project_id=' +
        $stateParams.project_id +
        '&download_type=' +
        type +
        '&link_id=' +
        $stateParams.link_id +
        '&download_type=' +
        type +
        '&data=' +
        encodedString +
        '&access_key_id=' +
        $scope.accessKey;

      // Check if the file is a ZIP file and if we want to unzip it
      if (isZipFile && isUnzipFile) {
        // Check browser support for File System Access API
        const browserSupport = await checkBrowserSupport();

        if (browserSupport.isSupported) {
          // If the browser supports File System Access API, extract the ZIP file
          $scope.openPopupWaiting('MY_EMAIL.UNZIP_PROGRESS');
          try {
            if (dirHandle) {
              await extractZipFileWithDirectory(url, dirHandle);
            } else {
              try {
                const selectedDirHandle = await getTargetDirectory();
                await extractZipFileWithDirectory(url, selectedDirHandle);
              } catch (dirError) {
                console.error('Failed to select directory:', dirError);
              }
            }
          } catch (error) {
            console.error('Error extracting ZIP file:', error);
            Util.createToast({
              className: 'error',
              content: Util.translate('MY_EMAIL.UNZIP_ERROR'),
            });
          } 
        }
      } else {
        if (isZipFile) {
          $scope.openPopupWaiting('MY_EMAIL.DECRYPT_ZIP_PROGRESS');
          downloadZipFile(url)
            .then(function (blob) {
              var downloadUrl = window.URL.createObjectURL(blob);
              var a = document.createElement('a');
              a.href = downloadUrl;
              var downloadName = name;
              if (downloadName && downloadName.toLowerCase().endsWith('.enc')) {
                downloadName = downloadName.substring(0, downloadName.length - 4);
              }
              a.download = downloadName || 'download.zip';
              document.body.appendChild(a);
              a.click();
              a.remove();
              window.URL.revokeObjectURL(downloadUrl);

              $rootScope.$broadcast('close_popup');
            })
            .catch(function (error) {
              console.error('Download failed:', error);
              $rootScope.$broadcast('close_popup');
              Util.createToast({
                className: 'danger',
                content: 'DOWNLOAD_ERR',
              });
            });
        } else {
          // For non-ZIP files, download normally
          $.fileDownload(url, { httpMethod: 'GET' })
            .done(function () {
              console.log('Download succeeded');
            })
            .fail(function (responseHtml, url, error) {
              console.error('Download failed:', error);
            });
        }
      }
    };

    // Download ZIP file from server
    async function downloadZipFile(url) {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error('Unable to download ZIP file');
      }
      return await response.blob();
    }

    // Read contents of the ZIP file
    async function readZipContents(zipBlob) {
      const zip = await JSZip.loadAsync(zipBlob);
      const fileEntries = Object.values(zip.files).filter((entry) => !entry.dir);

      if (fileEntries.length === 0) {
        throw new Error('Empty ZIP file');
      }

      return { zip, fileEntries };
    }

    // Get target directory for extraction
    async function getTargetDirectory() {
      return await window.showDirectoryPicker({
        id: 'extractZip',
        mode: 'readwrite',
        startIn: 'downloads',
      });
    }

    // Create or open subdirectory in the target directory (optional)
    async function getOrCreateSubdirectory(dirHandle, pathParts) {
      let currentDirHandle = dirHandle;

      for (const part of pathParts) {
        if (!part) continue; // Skip empty elements

        try {
          // Create or open a subfolder
          currentDirHandle = await currentDirHandle.getDirectoryHandle(part, { create: true });
        } catch (err) {
          console.error('Error when create folder:', part, err);
        }
      }

      return currentDirHandle;
    }

    // Save a file to the directory
    async function saveFileToDirectory(dirHandle, fileName, content) {
      const fileHandle = await dirHandle.getFileHandle(fileName, { create: true });
      const writable = await fileHandle.createWritable();

      await writable.write(content);
      await writable.close();
    }

    /**
     * Extracts a ZIP file from a provided URL and saves its contents to a user-selected directory.
     *
     * This function performs the following tasks:
     * 1. Downloads the ZIP file from the server using the Fetch API.
     * 2. Reads and parses the ZIP file contents using the JSZip library.
     * 3. Iterates through the files in the ZIP archive and maintains the folder structure.
     * 4. Prompts the user to select a target directory using the File System Access API.
     * 5. Creates necessary subdirectories in the target directory to match the ZIP file's structure.
     * 6. Saves each file to the appropriate location in the selected directory.
     * 7. Displays progress notifications during the extraction process.
     * 8. Shows a success message upon completion or an error message if the process fails.
     *
     * @param {string} url - The URL from which to download the ZIP file.
     * @param {FileSystemDirectoryHandle} dirHandle - The directory handle where the files will be extracted.
     * @returns {Promise<void>} - A promise that resolves when the extraction is complete.
     * @throws Will throw an error if any part of the process fails.
     *
     * @requires JSZip - A library for reading and writing ZIP files.
     * @requires File System Access API - A modern browser API for file system operations.
     */
    async function extractZipFileWithDirectory(url, dirHandle) {
      try {
        // Download the ZIP file from the provided URL
        const zipBlob = await downloadZipFile(url);

        // Read the ZIP file contents using JSZip
        const { zip, fileEntries } = await readZipContents(zipBlob);

        // Use the provided directory handle
        for (const entry of fileEntries) {
          try {
            // Convert the file content to an ArrayBuffer
            const content = await entry.async('arraybuffer');

            // Split the entry name into parts to handle subdirectories
            const pathParts = entry.name.split('/');
            const fileName = pathParts.pop();

            // Get or create the subdirectory in the target directory
            const targetDir = await getOrCreateSubdirectory(dirHandle, pathParts);

            // Save the file to the target directory
            await saveFileToDirectory(targetDir, fileName, content);
          } catch (error) {
            console.error('Error unzip file:', entry.name, error);
          }
        }
        // Close the waiting modal
        $rootScope.$broadcast('close_popup');

        // Show completion message
        Util.createToast({
          className: 'success',
          content: Util.translate('MY_EMAIL.UNZIP_SUCCESS'),
        });
        console.log('Unzip completed successfully');
      } catch (error) {
        // Close the waiting modal
        $rootScope.$broadcast('close_popup');
        console.error('Error extract zip function:', error);
        throw error; // Re-throw để caller có thể handle
      }
    }

    // Check if the browser supports File System Access API
    async function checkBrowserSupport() {
      let isFileSystemAccessApiSupported = false;

      try {
        // Check if showDirectoryPicker is available
        isFileSystemAccessApiSupported =
          'showDirectoryPicker' in window && typeof window.showDirectoryPicker === 'function';

        // Check if navigator.storage.getDirectory is available
        if (isFileSystemAccessApiSupported) {
          try {
            // Check if getDirectoryHandle is available
            isFileSystemAccessApiSupported =
              isFileSystemAccessApiSupported &&
              'getDirectoryHandle' in
                Object.getPrototypeOf(await window.navigator.storage.getDirectory());
          } catch (error) {
            // If there is an error when calling storage API, consider it unsupported
            isFileSystemAccessApiSupported = false;
          }
        }
      } catch (error) {
        // If there is any error, consider it unsupported
        isFileSystemAccessApiSupported = false;
      }

      // Check if the browser is Chromium-based
      const isChromiumBased =
        /Chrome|Edge|Edg|OPR/.test(navigator.userAgent) &&
        /Google Inc|Microsoft|Opera/.test(navigator.vendor);

      return {
        isFileSystemAccessApiSupported,
        isChromiumBased,
        isSupported: isFileSystemAccessApiSupported && isChromiumBased,
      };
    }

    //Check the browser is IE or edge
    function detectBrowsers() {
      var getBrowserIEOrEdg = true;
      var isIE = /*@cc_on!@*/ !!document.documentMode;
      // Edge 20+
      var isEdge = !isIE && !!window.StyleMedia;
      // Chrome 1 - 71
      var isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
      var isEdgeChromium = isChrome && navigator.userAgent.indexOf('Edg') !== -1;

      if (!isIE && !isEdge && !isEdgeChromium) {
        getBrowserIEOrEdg = false;
      }
      return getBrowserIEOrEdg;
    }

    $scope.showViewOnline = function (item, email) {
      // var newTab = window.open('about:blank', '_blank');
      var data = {
        email: email,
        os: '',
      };
      var myJSON = JSON.stringify(data);
      var encodedString = window.btoa(myJSON.toString());

      var params = {
        file_id: item.id,
        data: encodedString,
        access_key_id: $scope.accessKey,
      };

      Util.createRequest(
        configServer.API_URL + '/files/view/link',
        'GET',
        params,
        function (response) {
          var status = response.status;
          if (status === 200) {
            var settingWm = JSON.parse($scope.link.watermark_setting);
            $scope.viewerUrl =
              AppConfig.VIEWER_URL +
              '?id=' +
              response.data.content_id +
              '&ak=' +
              response.data.key_id +
              '&pr=' +
              ($scope.link.printable === 1 ? 1 : 0);
            if (settingWm.show_wm === 1 && settingWm.default_wm === 1) {
              settingWm.setting = {
                wm_text:
                  (email ? email + ' ' : '') +
                  new Date().toLocaleDateString('en-US', {
                    month: '2-digit',
                    day: '2-digit',
                    year: 'numeric',
                  }),
                wm_font_size: 50,
                wm_position: 'diagonal',
                wm_color: 'RGB(0,0,0)',
              };
            }

            if (settingWm.show_wm === 1) {
              $scope.viewerUrl +=
                '&wc=' +
                settingWm.setting.wm_color +
                '&ws=' +
                settingWm.setting.wm_font_size +
                '&wp=' +
                settingWm.setting.wm_position +
                '&wt=' +
                settingWm.setting.wm_text;
            }
            showViewOnlineModal($scope.viewerUrl);
            // if (newTab) {
            //   newTab.location.href = $scope.viewerUrl;
            // } else {
            //   window.open($scope.viewerUrl, '_blank');
            // }
          } else {
            if (newTab) newTab.close();
            Util.createToast({
              className: 'danger',
              content: 'SERVER_ERROR.' + status,
            });
          }
        },
        function (error) {
          if (newTab) newTab.close();
          Util.createToast({
            className: 'danger',
            content: 'SERVER_ERROR.' + error.status,
          });
        }
      );
    };

    function showViewOnlineModal(viewerUrl) {
      return $uibModal
        .open({
          templateUrl: 'components/modal-template/view_online_modal.html',
          size: 'xl',
          backdrop: 'static',
          controller: [
            '$scope',
            '$rootScope',
            '$uibModalInstance',
            function ($scope, $rootScope, $uibModalInstance) {
              $scope.onClose = function () {
                $uibModalInstance.close();
              };
              $scope.viewerUrl = viewerUrl;

              $timeout(function () {
                var iframe = document.querySelector('iframe');
                if (iframe) {
                  iframe.addEventListener('load', function () {
                    this.focus();
                    console.log('Iframe loaded and focused successfully');
                  });
                }
              });
            },
          ],
        })
        .result.catch(function (resp) {
          if (['cancel', 'backdrop click', 'escape key press'].indexOf(resp) === -1) {
            throw resp;
          }
        });
    }

    function getExtension(path) {
      var basename = /[^/\\&\?]+\.\w{3,4}(?=([\?#&].*$|$))/g.exec(path);
      var fileName = basename && basename[0];
      return fileName && fileName.split('.').pop();
    }

    function openModalDownloadOrUnzipAndSaveFolder(file) {
      return $uibModal
        .open({
          templateUrl: 'components/modal-template/confirm_download_or_unzip_and_save_folder.html',
          size: 'md',
          resolve: {
            file: function () {
              return file;
            },
            downloadFunction: function () {
              return $scope.downloadSingleFile;
            },
          },
          controller: [
            '$scope',
            '$uibModalInstance',
            '$translate',
            'file',
            'downloadFunction',
            function ($scope, $uibModalInstance, $translate, file, downloadFunction) {
              $translate([
                'VIEW_DOWNLOAD.CONFIRM_DOWNLOAD_OR_UNZIP_AND_SAVE_FOLDER_TITLE',
                'VIEW_DOWNLOAD.CONFIRM_DOWNLOAD_OR_UNZIP_AND_SAVE_FOLDER_MSG',
                'VIEW_DOWNLOAD.JUST_DOWNLOAD_BUTTON',
                'VIEW_DOWNLOAD.DOWNLOAD_AND_UNZIP_SAVE_BUTTON',
              ]).then(function (translations) {
                $scope.opts = {
                  title:
                    translations['VIEW_DOWNLOAD.CONFIRM_DOWNLOAD_OR_UNZIP_AND_SAVE_FOLDER_TITLE'],
                  message:
                    translations['VIEW_DOWNLOAD.CONFIRM_DOWNLOAD_OR_UNZIP_AND_SAVE_FOLDER_MSG'],
                  justDownloadLabel: translations['VIEW_DOWNLOAD.JUST_DOWNLOAD_BUTTON'],
                  downloadAndUnzipLabel:
                    translations['VIEW_DOWNLOAD.DOWNLOAD_AND_UNZIP_SAVE_BUTTON'],
                };
                $scope.onClose = function () {
                  $uibModalInstance.close();
                };

                $scope.onJustDownload = function () {
                  downloadFunction(file.id, file.name);
                  $uibModalInstance.close();
                };

                $scope.onUnzipAndSaveFolder = function () {
                  var isUnzip = true;
                  // Call getTargetDirectory() first to ensure user gesture
                  getTargetDirectory()
                    .then(function (dirHandle) {
                      // Call doDownload with dirHandle selected
                      downloadFunction(file.id, file.name, isUnzip, dirHandle);
                    })
                    .catch(function (error) {
                      console.error('Failed to select directory:', error);
                       Util.createToast({
                         className: 'warning',
                         content: Util.translate('MY_EMAIL.SELECT_DIRECTORY_ERROR'),
                       });
                    });
                  $uibModalInstance.close();
                };

                // close modal
                $scope.$on('close_modal', closeModal);

                function closeModal(event, value) {
                  $uibModalInstance.close();
                }
              });
            },
          ],
        })
        .result.catch(function (resp) {
          if (['cancel', 'backdrop click', 'escape key press'].indexOf(resp) === -1) {
            throw resp;
          }
        });
    }

    function openModalDownloadZip() {
      return $uibModal
        .open({
          templateUrl: 'components/modal-template/confirm_download_zip_modal.html',
          size: 'md',
          controller: [
            '$scope',
            '$uibModalInstance',
            '$translate',
            function ($scope, $uibModalInstance, $translate) {
              $translate([
                'VIEW_DOWNLOAD.DOWNLOAD_ZIP_CONTENT',
                'VIEW_DOWNLOAD.DOWNLOAD_ZIP_TITLE',
              ]).then(function (translations) {
                $scope.opts = {
                  title: translations['VIEW_DOWNLOAD.DOWNLOAD_ZIP_TITLE'],
                  message: translations['VIEW_DOWNLOAD.DOWNLOAD_ZIP_CONTENT'],
                };
                $scope.onClose = function () {
                  $uibModalInstance.close();
                };

                // close modal
                $scope.$on('close_modal', closeModal);

                function closeModal(event, value) {
                  $uibModalInstance.close();
                }
              });
            },
          ],
        })
        .result.catch(function (resp) {
          if (['cancel', 'backdrop click', 'escape key press'].indexOf(resp) === -1) {
            throw resp;
          }
        });
    }
    //end controller

    // =================== reply function ===================

    $scope.isUploadingFile = false;
    $scope.isUploadingFolder = false;

    $scope.selectFile = function (e) {
      $scope.isUploadingFile = true;
      $scope.$apply();
      var uploadFile = e.target.files;
      for (var i = 0; i < uploadFile.length; i++) {
        if (uploadFile[i].size === 0) {
          Util.createToast({ className: 'danger', content: 'ERROR.EMPTY_DOCUMENT_FILE' });
          continue;
        }
        if ($scope.listReplyFile.findIndex((s) => s.file.name === uploadFile[i].name) === -1) {
          var file = {
            file: uploadFile[i],
            isUpload: false,
          };
          $scope.listReplyFile.push(file);
        }
      }
      $('#fileUpload').val('');
      $scope.isUploadingFile = false;
      $scope.$apply();
    };

    $scope.doRemoveFileFromListReply = function (file) {
      var index = $scope.listReplyFile.findIndex((s) => s.file.name === file.name);
      if (index !== -1) {
        $scope.listReplyFile.splice(index, 1);
      }
    };

    $scope.openPopupWaiting = function (messageKey = 'MY_EMAIL.REPLY_SENDER') {
      //show confirm revoke
      return $uibModal
        .open({
          templateUrl: 'components/modal-template/please-wait-modal.html',
          size: 'md',
          backdrop: 'static',
          keyboard: false,
          controller: [
            '$scope',
            '$uibModalInstance',
            'AppUtil',
            'Util',
            'configServer',
            function ($scope, $uibModalInstance, AppUtil, Util, configServer) {
              $scope.opts = {
                message: Util.translate(messageKey),
              };

              // close modal
              $scope.$on('close_popup', closeModal);

              function closeModal(event, value) {
                $uibModalInstance.close();
              }
            },
          ],
        })
        .result.catch(function (resp) {
          if (['cancel', 'backdrop click', 'escape key press'].indexOf(resp) === -1) throw resp;
        });
    };

    // upload file & send notification reply
    $scope.doReply = function (replyFrm) {
      // do upload file : promise
      var reqs = [];
      var i = 0;
      var allSuccess;

      while (i < $scope.listReplyFile.length) {
        if ($scope.listReplyFile[i].isUpload) {
          i++;
          continue;
        }
        let fd = new FormData();
        // do upload
        fd.append('file', $scope.listReplyFile[i].file);
        fd.append('file_name', $scope.listReplyFile[i].file.name);
        fd.append('folder_id', $scope.folderPathId);
        fd.append('project_id', $scope.link.project_id);

        i++;

        reqs.push(
          $.ajax({
            method: 'POST',
            url: configServer.API_URL + '/upload/files',
            data: fd,
            contentType: false,
            processData: false,
            headers: {
              'auth-token': $scope.stk,
            },
            dataType: 'json',
          })
            .done(function (response) {
              if (response.status !== 200) {
                Util.createToast({
                  className: 'danger',
                  content: 'SERVER_ERROR.' + response.status,
                });
                return;
              }

              $scope.listFileSuccess.push(response.data.file.file_id);
              allSuccess = response.status;
            })
            .fail(function (xhr, status, error) {
              Util.createToast({ className: 'danger', content: 'SERVER_ERROR.' + xhr.status });
              if (xhr.status === 401) {
                window.location.reload();
              }
              $rootScope.$broadcast('close_popup');
              $scope.isReply = false;
            })
        );
      }

      if (reqs.length > 0) {
        // Post all reqs
        $q.all(reqs).then(function (data) {
          if (allSuccess === 200) {
            // reply send mail
            $.ajax({
              method: 'POST',
              url: configServer.API_URL + '/notification/email/secure/reply',
              data: JSON.stringify({
                link_id: $stateParams.link_id,
                folder_id: $scope.folderPathId,
                subject: $scope.reply.subject,
                sender_email: $scope.linkAuthen.email,
                message: $scope.reply.message,
              }),
              contentType: 'application/json;charset=utf-8',
              dataType: 'json',
              headers: {
                'auth-token': $scope.stk,
              },
            })
              .done(function (response) {
                if (response.status === 200) {
                  $scope.listReplyFile = [];
                  $scope.listFileSuccess = [];
                  $scope.reply.subject = '';
                  $scope.reply.message = '';
                  $scope.folderPathId = '';

                  // Reset status form
                  if (replyFrm) {
                    replyFrm.$setPristine();
                    replyFrm.$setUntouched();
                  }
                  // create toast success
                  Util.createToast({
                    className: 'success',
                    content: 'COMMON.MESSAGE.REPLY_SUCCESS',
                  });
                } else {
                  Util.createToast({
                    className: 'danger',
                    content: 'SERVER_ERROR.' + response.status,
                  });
                  if (response.status === 401) {
                    window.location.reload();
                  }
                }
              })
              .fail(function (xhr, status, error) {
                Util.createToast({ className: 'danger', content: 'SERVER_ERROR.' + xhr.status });
                if (xhr.status === 401) {
                  window.location.reload();
                }
                $rootScope.$broadcast('close_popup');
                $scope.isReply = false;
              });
          } else if (allSuccess !== 200 && allSuccess !== undefined) {
            // toast fail
            Util.createToast({
              className: 'danger',
              content: 'SERVER_ERROR.' + allSuccess,
            });
            if (allSuccess === 401) {
              window.location.reload();
            }
          }
          // close popup
          $rootScope.$broadcast('close_popup');
          $scope.isReply = false;
        });
      }
    };

    $scope.onExit = function () {
      for (var i = 0; i < $scope.listFileSuccess.length; i++) {
        $.ajax({
          method: 'DELETE',
          url: configServer.API_URL + '/trash/items/physical?file_id=' + $scope.listFileSuccess[i],
          headers: {
            'auth-token': $scope.stk,
          },
        })
          .done(function (response) {})
          .fail(function (xhr, status, error) {});
      }
      return 'bye bye';
    };

    $scope.createReplyPath = function (valid, replyFrm) {
      if (!valid || $scope.isReply) {
        return;
      }
      if ($scope.listReplyFile.length === 0) {
        Util.createToast({
          className: 'danger',
          content: 'ERROR.PLEASE_ATTACH_FILE',
        });
        return;
      }

      // // show popup please wait
      // $scope.openPopupWaiting();
      $scope.isReply = true;

      $.ajax({
        method: 'POST',
        url: configServer.API_URL + '/notification/email/secure/path',
        data: JSON.stringify({
          link_id: $stateParams.link_id,
          sender_email: $scope.linkAuthen.email,
        }),
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        headers: {
          'auth-token': $scope.stk,
        },
      })
        .done(function (response) {
          if (response.status === 200) {
            $scope.folderPathId = response.data.folder_id;
            $scope.openPopupWaiting('MY_EMAIL.REPLY_SENDER');
            $scope.doReply(replyFrm);
          } else {
            Util.createToast({ className: 'danger', content: 'SERVER_ERROR.' + response.status });
            if (response.status === 401) {
              window.location.reload();
            }
            $rootScope.$broadcast('close_popup');
            $scope.isReply = false;
          }
        })
        .fail(function (xhr, status, error) {
          Util.createToast({ className: 'danger', content: 'SERVER_ERROR.' + xhr.status });
          if (xhr.status === 401) {
            window.location.reload();
          }
          $rootScope.$broadcast('close_popup');
          $scope.isReply = false;
        });
    };

    $scope.selectFolder = async function (e) {
      $scope.isUploadingFolder = true;
      $scope.$apply();

      const files = e.target.files;
      if (!files || files.length === 0) {
        Util.createToast({ className: 'danger', content: 'ERROR.EMPTY_FOLDER' });
        $scope.isUploadingFolder = false;
        $scope.$apply();
        return;
      }

      const firstFile = files[0];
      const folderName = firstFile.webkitRelativePath.split('/')[0];
      const zip = new JSZip();
      for (let file of files) {
        const relativePath = file.webkitRelativePath || file.name;
        zip.file(relativePath, file);
      }

      try {
        const zipBlob = await zip.generateAsync({ type: 'blob' });
        const zipFile = new File([zipBlob], `${folderName}.zip`, { type: 'application/zip' });

        $scope.listReplyFile.push({
          file: zipFile,
          isUpload: false,
        });
        $scope.isUploadingFolder = false;
        $scope.$apply();
      } catch (error) {
        console.error('Error creating zip file:', error);
        Util.createToast({ className: 'danger', content: 'ERROR.ZIP_CREATION_FAILED' });
        $scope.isUploadingFolder = false;
        $scope.$apply();
      }

      $('#folderUpload').val('');
    };

    window.addEventListener('beforeunload', function (event) {});

    // page reload or close tab
    angular.element($window).on('beforeunload', function () {
      if ($rootScope.toState.name === 'linkViewDownload') {
        $scope.onExit();
      }
    });
    // change route
    $rootScope.$on(
      '$stateChangeStart',
      function (event, toState, toParams, fromState, fromParams, options) {
        if (
          $rootScope.toState.name === 'linkViewDownload' &&
          (toState.name !== fromState.name ||
            toParams.link_id !== fromParams.link_id ||
            toParams.project_id !== fromParams.project_id)
        ) {
          $scope.onExit();
        }
      }
    );
  },
]);
