import UIKit
import VisionKit
import ImagePicker

final class DocumentsTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    struct Constants {
        static let reuseIdentifier = String(describing: DocumentsTableViewController.self)
        static let storyboardName = "Documents"
        static let rowHeight: CGFloat = 112
        static let cellReuseIdentifier = String(describing: DocumentsTableViewCell.self)
        
        static let topBottom: CGFloat = 120
        static let margin: CGFloat = 64
    }
    
    static func buildViewController() -> DocumentsTableViewController {
        let controller = UIStoryboard(name: Constants.storyboardName,
                                      bundle: .main).instantiateViewController(withIdentifier: Constants.reuseIdentifier)
        return controller as! DocumentsTableViewController
    }
    
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var AllFolderView: AllFolderTableViewCell!
    @IBOutlet weak var fixedTableSheet: UIView!
    @IBOutlet weak var searchForFilesView: SearchFilesView!
    
    private var viewModels: [File] = []
    private var searchedViewModel: [File] = []
    
    private var localFileManager: LocalFileManager?
    private var sortType: SortyFileType = .date
    
    //    private let noDocumentsimageView = UIImageView(image: UIImage(named: "box"))
    private var renameAlertController: UIAlertController?
    private var renameFileName: String?
    private var selectedFolder: AppConfigurator.Folder?
    private var isSearching: Bool = false
    private var pageViewControllers: [UIViewController] = []
    
    @IBOutlet weak var allFolderView_height: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "File Manager"
        let settingsButton = UIBarButtonItem(image: UIImage(named: "settings"), style: .done, target: self, action: #selector(openSettings))
        navigationItem.rightBarButtonItem = settingsButton
        
        tableView.register(UINib(nibName: "DocumentsTableViewCell", bundle: nil), forCellReuseIdentifier: "DocumentsTableViewCell")
        
        tableView.tableFooterView = UIView()
        tableView.delegate = self
        tableView.dataSource = self
        
        tableView.reloadData()
        
        let savedFolders = AppConfigurator().getFolders()
        for item in savedFolders {
            if item.isSelected == true {
                selectedFolder = item
            }
        }
        
        if let folder = selectedFolder {
            AllFolderView?.set(selectedFolder: folder, delegate: self)
        }
        searchForFilesView.delegate = self
        localFileManager = LocalFileManager()
        
        tabBarController?.delegate = UIApplication.shared.delegate as? UITabBarControllerDelegate
        
        NotificationCenter.default.addObserver(self, selector: #selector(middleButtonTapped(_:)),
                                               name: NSNotification.Name.MiddleButtonTapped, object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(fetchViewModels),
                                               name: NSNotification.Name.ReloadViewModels, object: nil)
        
        NotificationCenter.default.addObserver(self, selector: #selector(rightButtonTapped(_:)),
                                               name: NSNotification.Name.rightButtonTapped, object: nil)
        if UserDefaults.standard.startsAppWithCamera {
            openCamera()
        }
        
        fixedTableSheet.layer.cornerRadius = 30
        fixedTableSheet.layer.shadowColor = UIColor.gray.cgColor
        fixedTableSheet.layer.shadowOffset = CGSize(width: 0, height: 2) // Shadow position
        fixedTableSheet.layer.shadowOpacity = 0.7 // Shadow opacity
        fixedTableSheet.layer.shadowRadius = 4.0
        fixedTableSheet.backgroundColor = .white // or any non-clear color
        fixedTableSheet.clipsToBounds = false
        fetchViewModels()
        
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
    
    @objc private func fetchViewModels() {
        if let folder = selectedFolder {
            guard let directoryURL = localFileManager?.getFolderUrl(folder: folder),
                  let viewModels = localFileManager?.filesForDirectory(directoryURL, sortType: sortType) else { return }
            self.viewModels = viewModels
            self.searchedViewModel = viewModels
            AllFolderView?.set(selectedFolder: folder, delegate: self)
            tableView.reloadData()
        }
    }
    
    @objc private func openSettings() {
        let settings = SettingViewController()
        self.navigationController?.pushViewController(settings, animated: false)
    }
    
    // MARK: - Table view data source
    
    func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return isSearching ? searchedViewModel.count :viewModels.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: Constants.cellReuseIdentifier,
                                                       for: indexPath) as? DocumentsTableViewCell else { return UITableViewCell() }
        
        // Configure the cell...
        let viewModel = isSearching ? searchedViewModel[indexPath.row ] : viewModels[indexPath.row]
        cell.configure(with: viewModel, image: localFileManager?.getThumbnail(for: viewModel.fileURL))
        
        return cell
        
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return Constants.rowHeight
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        return UIView()
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        20
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let viewModel = isSearching ? searchedViewModel[indexPath.row] : viewModels[indexPath.row]
        let controller = DocumentPreviewViewController.buildViewController()
        controller.file = viewModel
        controller.hidesBottomBarWhenPushed = true
        navigationController?.pushViewController(controller, animated: true)
    }
    
    func tableView(_ tableView: UITableView,
                   editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
        return .none
    }
    
    func tableView(_ tableView: UITableView,
                   trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        
        // Trash action
        let trash = UIContextualAction(style: .destructive,
                                       title: "Delete".localized) { [weak self] (_, _, completionHandler) in
            self?.deleteFile(at: indexPath)
            completionHandler(true)
        }
        trash.backgroundColor = .systemRed
        trash.image = UIImage(systemName: "trash")?.tint(with: .white)
        
        // Rename action
        let rename = UIContextualAction(style: .normal,
                                        title: "Rename".localized) { [weak self] (_, _, completionHandler) in
            self?.renameFile(at: indexPath)
            completionHandler(true)
        }
        rename.backgroundColor = UIColor.black.withAlphaComponent(0.5)
        rename.image = UIImage(systemName: "square.and.pencil")?.tint(with: .white)
        
        let configuration = UISwipeActionsConfiguration(actions: [trash, rename])
        configuration.performsFirstActionWithFullSwipe = true
        
        return configuration
    }
    
    @objc private func middleButtonTapped(_ notification: NSNotification) {
        openCamera()
    }
    
    @objc private func rightButtonTapped(_ notification: NSNotification) {
        openGallery()
    }
    
    
    private func openCamera() {
        let scannerOptions = ImageScannerOptions(scanMultipleItems: true,
                                                 allowAutoScan: false,
                                                 allowTapToFocus: false,
                                                 defaultColorRenderOption:.color)
        let scannerViewController = ScannerViewController(scanSession: nil, options: scannerOptions)
        
        
        scannerViewController.delegate = self
        
        scannerViewController.hidesBottomBarWhenPushed = true
        self.navigationController?.pushViewController(scannerViewController, animated: true)
//
//        scannerViewController.modalPresentationStyle = .overFullScreen
//        self.present(scannerViewController, animated: true)
    }
    
    private func openGallery() {
        
        let imagePickerController = ImagePickerController()
        imagePickerController.expandGalleryView()
        imagePickerController.delegate = self
        imagePickerController.modalPresentationStyle = .fullScreen
        present(imagePickerController, animated: true, completion: nil)
    }
    
    private func renameFile(at indexPath: IndexPath) {
        let viewModel = isSearching ? searchedViewModel[indexPath.row] : viewModels[indexPath.row]
        renameAlertController = UIAlertController(title: "Rename document".localized, message: nil, preferredStyle: .alert)
        
        renameAlertController!.addTextField { [weak self] textField in
            guard let self = self else { return }
            textField.placeholder = viewModel.displayName
            textField.text = viewModel.displayName
            textField.clearButtonMode = .always
            self.renameFileName = viewModel.displayName
            textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged)
        }
        
        let continueAction = UIAlertAction(title: "Rename".localized,
                                           style: .default) { [weak self] _ in
            guard let self = self else { return }
            guard let textFields = self.renameAlertController?.textFields else { return }
            
            if let newName = textFields.first?.text, newName != viewModel.displayName {
                do {
                    try self.localFileManager?.renameFile(at: viewModel.fileURL, withName: newName)
                    self.fetchViewModels()
                } catch {
                    return
                }
            }
        }
        
        renameAlertController!.addAction(continueAction)
        renameAlertController!.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
        renameAlertController?.actions.first?.isEnabled = false
        present(renameAlertController!, animated: true)
    }
    
    private func deleteFile(at indexPath: IndexPath) {
        let viewModel = isSearching ? searchedViewModel[indexPath.row] : viewModels[indexPath.row]
        
        if UserDefaults.standard.askOnSwipeDelete {
            let alertController = UIAlertController(title: Bundle.appName,
                                                    message: "Are you sure you want to delete this document?".localized, preferredStyle: .alert)
            
            let okAction = UIAlertAction(title: "Yes, delete!".localized, style: .destructive, handler: { [weak self] action in
                guard let self = self else { return }
                
                self.delete(file: viewModel.fileURL, at: indexPath)
            })
            
            alertController.addAction(okAction)
            
            alertController.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
            alertController.popoverPresentationController?.sourceView = tableView.cellForRow(at: indexPath)
            present(alertController, animated: true)
        } else {
            delete(file: viewModel.fileURL, at: indexPath)
        }
    }
    
    private func delete(file fileURL: URL, at indexPath: IndexPath) {
        do {
            try self.localFileManager?.filesManager.removeItem(at: fileURL)
            try self.localFileManager?.removeThumbnail(for: fileURL)
            if isSearching {
                self.searchedViewModel.remove(at: indexPath.row)
            } else {
                self.viewModels.remove(at: indexPath.row)
            }
            self.tableView.deleteRows(at: [indexPath], with: .fade)
        } catch {
            return
        }
    }
    
    
}

/// Tells the delegate that the user picked a still image.
extension DocumentsTableViewController: UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    func imagePickerController(_ picker: UIImagePickerController,
                               didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true) { [weak self] in
            guard let self = self else { return }
            guard let image = info[UserDefaults.standard.isPhotoEditigOn ? UIImagePickerController.InfoKey.editedImage : UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
            if let folder = selectedFolder {
                PDFManager.createPDFDocument(from: image, localFileManager: self.localFileManager, folder: folder)
                self.fetchViewModels()
                self.tabBarController?.selectedIndex = 0
            }
        }
    }
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true) { [weak self] in
            self?.tabBarController?.selectedIndex = 0
        }
    }
}

extension DocumentsTableViewController: ImageScannerControllerDelegate {
    func imageScannerController(_ scanner: ImageScannerController, didFinishWithSession session: MultiPageScanSession) {
        var images = [URL]()
        
        for index in 0..<session.scannedItems.count {
            if let url = session.scannedItems[index].renderedImage {
                images.append(url)
            }
        }
        print("images: \(images)")
        if let folder = selectedFolder {
            PDFManager.createMultiPDFPage(from: images, localFileManager: localFileManager, folder: folder) {
                scanner.dismiss(animated: true) {
                    self.fetchViewModels()
                }
            }
        }
    }
    
    func imageScannerControllerDidCancel(_ scanner: ImageScannerController) {
        scanner.dismiss(animated: true)
    }
    
    func imageScannerController(_ scanner: ImageScannerController, didFailWithError error: Error) {
        scanner.dismiss(animated: true)
        
    }
    
    @objc func textFieldDidChange(_ textField: UITextField) {
        guard let text = textField.text, let renameFileName = renameFileName,
              renameFileName != text, !text.trimmingCharacters(in: .whitespaces).isEmpty else {
            renameAlertController?.actions.first?.isEnabled = false
            return
        }
        
        renameAlertController?.actions.first?.isEnabled = true
    }
}

extension DocumentsTableViewController: ScannerViewControllerDelegate {
    func scannerViewController(_ scannerViewController: ScannerViewController, reviewItems inSession: MultiPageScanSession) {
        let multipageScanViewController = MultiPageScanSessionViewController(scanSession: inSession)
        multipageScanViewController.delegate = self
        self.navigationController?.pushViewController(multipageScanViewController, animated: true)
        
    }
    
    func scannerViewController(_ scannerViewController: ScannerViewController, didFail withError: Error) {
        scannerViewController.dismiss(animated: true)
    }
    
    func scannerViewControllerDidCancel(_ scannerViewController: ScannerViewController) {
        scannerViewController.dismiss(animated: true)
    }
}

extension DocumentsTableViewController: AllFolderTableViewCellDelegate {
    func addFolderTapped() {
        alert(confirm: "Add Folder", destructive: "Cancel", message: "Add Folder?"){ folderName in
            let newFolder = AppConfigurator.Folder(name: folderName, savedName: folderName.replacingOccurrences(of: " ", with: "_"), isSelected: false)
            var currentFolders = AppConfigurator().getFolders()
            currentFolders.append(newFolder)
            if let encoded = try? JSONEncoder().encode(currentFolders) {
                UserDefaults.standard.set(encoded, forKey: "folders")
                self.AllFolderView?.refresh()
                self.dismiss(animated: true)
            }
        }
    }
    
    func cellTapped(folder: AppConfigurator.Folder) {
        selectedFolder = folder
        fetchViewModels()
    }
}

extension DocumentsTableViewController: SearchFilesViewDelegate {
    func searchfor(text: String) {
        if text.count == 0 {
            isSearching = false
            UIView.animate(withDuration: 0.5) {
                self.allFolderView_height.constant = 240
                self.AllFolderView.isHidden = false
            }
        } else {
            isSearching = true
            self.searchedViewModel =  self.viewModels.filter { $0.displayName.lowercased().contains(text.lowercased()) }
        }
        tableView.reloadData()
    }
}

extension DocumentsTableViewController: ImagePickerDelegate {
    
    func wrapperDidPress(_ imagePicker: ImagePicker.ImagePickerController, images: [UIImage]) {
        guard !images.isEmpty else { return }
        
        // Create a view controller for each image
        let viewControllers = images.map { image -> UIViewController in
            let viewController = UIViewController()
            viewController.view.backgroundColor = .white
            
            let imageView = UIImageView(image: image)
            imageView.contentMode = .scaleAspectFit
            imageView.translatesAutoresizingMaskIntoConstraints = false
            
            viewController.view.addSubview(imageView)
            NSLayoutConstraint.activate([
                imageView.leadingAnchor.constraint(equalTo: viewController.view.leadingAnchor),
                imageView.trailingAnchor.constraint(equalTo: viewController.view.trailingAnchor),
                imageView.topAnchor.constraint(equalTo: viewController.view.topAnchor),
                imageView.bottomAnchor.constraint(equalTo: viewController.view.bottomAnchor)
            ])
            
            return viewController
        }
        
        self.pageViewControllers = viewControllers
        // Create a page view controller to allow the user to scroll through the images
        let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
        pageViewController.dataSource = self
        
        pageViewController.setViewControllers([viewControllers[0]], direction: .forward, animated: false, completion: nil)
        
        // Present the page view controller
        imagePicker.present(pageViewController, animated: true, completion: nil)
    }
    
    
    func doneButtonDidPress(_ imagePicker: ImagePicker.ImagePickerController, images: [UIImage]) {
        imagePicker.dismiss(animated: true) { [weak self] in
            guard let self = self else { return }
            if let folder = selectedFolder {
                PDFManager.createMultiImagesPDFDocument(from: images, localFileManager: self.localFileManager, folder: folder)
                self.fetchViewModels()
                self.tabBarController?.selectedIndex = 0
            }
        }
    }
    
    func cancelButtonDidPress(_ imagePicker: ImagePicker.ImagePickerController) {
        imagePicker.dismiss(animated: true) { [weak self] in
            self?.tabBarController?.selectedIndex = 0
        }
    }
}
extension DocumentsTableViewController: MultiPageScanSessionViewControllerDelegate {
    
    public func multiPageScanSessionViewController(_ multiPageScanSessionViewController: MultiPageScanSessionViewController,
                                                   finished session: MultiPageScanSession) {
        var images = [URL]()
        for index in 0..<session.scannedItems.count {
            if let url = session.scannedItems[index].renderedImage {
                images.append(url)
            }
        }
        print("images: \(images)")
        if let folder = selectedFolder {
            PDFManager.createMultiPDFPage(from: images, localFileManager: localFileManager, folder: folder) {
                self.fetchViewModels()
                self.navigationController?.popViewController(animated: true)
            }
        }
    }
}

extension DocumentsTableViewController: UIPageViewControllerDataSource {
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        guard let index = pageViewControllers.firstIndex(of: viewController), index > 0 else {
            return nil
        }
        return pageViewControllers[index - 1]
    }
    
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        guard let index = pageViewControllers.firstIndex(of: viewController), index < pageViewControllers.count - 1 else {
            return nil
        }
        return pageViewControllers[index + 1]
    }
}