import UIKit
import VisionKit

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!
    
    private var viewModels: [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?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "File Manager"
        tableView.tableFooterView = UIView()
        tableView.delegate = self
        tableView.dataSource = self
        
        tableView.register(UINib(nibName: "DocumentsTableViewCell", bundle: nil), forCellReuseIdentifier: "DocumentsTableViewCell")
        
        let savedFolders = AppConfigurator().getFolders()
           for item in savedFolders {
               if item.isSelected == true {
                   selectedFolder = item
               }
           }
        
        if let folder = selectedFolder {
            AllFolderView?.set(selectedFolder: folder, 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)
        
        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
            AllFolderView?.set(selectedFolder: folder, delegate: self)
            tableView.reloadData()
        }
    }
    
    // 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 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 = 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 = 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) {
        let alertController = UIAlertController(title: nil,
                                                message: nil, preferredStyle: .actionSheet)
        
        let cameraAction = UIAlertAction(title: "Camera".localized, style: .default, handler: { action in
            self.openCamera()
        })
        
        let galleryAction = UIAlertAction(title: "Gallery".localized, style: .default, handler: { action in
            self.openGallery()
        })
        
        alertController.addAction(cameraAction)
        cameraAction.setValue(UIImage(systemName: "camera"), forKey: "image")
        cameraAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
        
        alertController.addAction(galleryAction)
        galleryAction.setValue(UIImage(systemName: "photo"), forKey: "image")
        galleryAction.setValue(CATextLayerAlignmentMode.left, forKey: "titleTextAlignment")
        
        alertController.addAction(UIAlertAction(title: "Cancel".localized, style: .cancel, handler: nil))
        alertController.popoverPresentationController?.sourceView = notification.object as? UIButton
        present(alertController, animated: true)
    }
    
    private func openCamera() {
        let scannerOptions = ImageScannerOptions(scanMultipleItems: true,
                                                 allowAutoScan: false,
                                                 allowTapToFocus: false,
                                                 defaultColorRenderOption:.color)
        let scannerViewController = ImageScannerController(options: scannerOptions)
        scannerViewController.imageScannerDelegate = self
        present(scannerViewController, animated: true)
    }
    
    private func openGallery() {
        guard UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) else { return }
        let imagePickerController = UIImagePickerController()
        imagePickerController.delegate = self
        
        imagePickerController.sourceType = UIImagePickerController.SourceType.savedPhotosAlbum
        imagePickerController.allowsEditing = UserDefaults.standard.isPhotoEditigOn
        present(imagePickerController, animated: true, completion: nil)
    }
    
    private func renameFile(at indexPath: IndexPath) {
        let viewModel = 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 = 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)
            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()
            }
        }
    }
}

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: AllFolderTableViewCellDelegate {
    func cellTapped(folder: AppConfigurator.Folder) {
        selectedFolder = folder
        fetchViewModels()
    }
}