//
// Copyright 2024 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//

import SignalServiceKit
import SignalUI

protocol RegistrationRestoreFromBackupPresenter: AnyObject {
    func didSelectBackup(type: RegistrationMessageBackupRestoreType)
    func skipRestoreFromBackup()
}

public enum RegistrationMessageBackupRestoreType {
    case local(fileUrl: URL)
    case remote
}

class RegistrationRestoreFromBackupViewController: OWSViewController {

    private weak var presenter: RegistrationRestoreFromBackupPresenter?

    public init(presenter: RegistrationRestoreFromBackupPresenter) {
        self.presenter = presenter
        super.init()
    }

    // MARK: Rendering

    // TODO[Backups]: localize
    private lazy var titleLabel: UILabel = {
        let result = UILabel.titleLabelForRegistration(
            text: "Restore from backup"
            // comment: "If a user is installing Signal on a new phone, they may be asked whether they want to restore their device from a backup."
        )
        return result
    }()

    // TODO[Backups]: localize
    private lazy var explanationLabel: UILabel = {
        let result = UILabel.explanationLabelForRegistration(text:
            "Restore message history from a local backup. Only media sent or received in the past 30 days is included."
            // comment: "If a userk is installing Signal on a new phone, they may be asked whether they want to restore their device from a backup. This is a description of that question."
        )
        return result
    }()

    private func choiceButton(
        title: String,
        body: String,
        iconName: String,
        selector: Selector
    ) -> OWSFlatButton {
        let button = OWSFlatButton()
        button.setBackgroundColors(upColor: Theme.isDarkThemeEnabled ? .ows_gray80 : .ows_gray02)
        button.layer.cornerRadius = 8
        button.clipsToBounds = true

        // Icon

        let iconContainer = UIView()
        let iconView = UIImageView(image: UIImage(named: iconName))
        iconView.contentMode = .scaleAspectFit
        iconContainer.addSubview(iconView)
        iconView.autoPinWidthToSuperview()
        iconView.autoSetDimensions(to: CGSize(square: 48))
        iconView.autoVCenterInSuperview()
        iconView.autoMatch(.height, to: .height, of: iconContainer, withOffset: 0, relation: .lessThanOrEqual)

        // Labels

        let titleLabel = UILabel()
        titleLabel.text = title
        titleLabel.numberOfLines = 0
        titleLabel.lineBreakMode = .byWordWrapping
        titleLabel.font = UIFont.dynamicTypeBody.semibold()
        titleLabel.textColor = Theme.primaryTextColor

        let bodyLabel = UILabel()
        bodyLabel.text = body
        bodyLabel.numberOfLines = 0
        bodyLabel.lineBreakMode = .byWordWrapping
        bodyLabel.font = .dynamicTypeBody2
        bodyLabel.textColor = Theme.secondaryTextAndIconColor

        let topSpacer = UIView.vStretchingSpacer()
        let bottomSpacer = UIView.vStretchingSpacer()

        let vStack = UIStackView(arrangedSubviews: [
            topSpacer,
            titleLabel,
            bodyLabel,
            bottomSpacer
        ])
        vStack.axis = .vertical
        vStack.spacing = 8

        topSpacer.autoMatch(.height, to: .height, of: bottomSpacer)

        // Disclosure Indicator

        let disclosureContainer = UIView()
        let disclosureView = UIImageView()
        disclosureView.setTemplateImage(
            UIImage(imageLiteralResourceName: "chevron-right-20"),
            tintColor: Theme.secondaryTextAndIconColor
        )
        disclosureView.contentMode = .scaleAspectFit
        disclosureContainer.addSubview(disclosureView)
        disclosureView.autoPinEdgesToSuperviewEdges()
        disclosureView.autoSetDimension(.width, toSize: 20)

        let hStack = UIStackView(arrangedSubviews: [
            iconContainer,
            vStack,
            disclosureContainer
        ])
        hStack.axis = .horizontal
        hStack.spacing = 16
        hStack.isLayoutMarginsRelativeArrangement = true
        hStack.layoutMargins = UIEdgeInsets(top: 24, leading: 16, bottom: 24, trailing: 16)
        hStack.isUserInteractionEnabled = false

        button.addSubview(hStack)
        hStack.autoPinEdgesToSuperviewEdges()

        button.addTarget(target: self, selector: selector)

        return button
    }

    // TODO[Backups]: localize
    private lazy var restoreFromBackupButton = choiceButton(
        title: "Restore Signal Backup",
        // comment: "The title for the device transfer 'choice' view 'transfer' option"
        body:
            "Restore all your text messages + your last 30 days of media",
        // comment: "The body for the device transfer 'choice' view 'transfer' option"
        iconName: Theme.iconName(.backup),
        selector: #selector(didSelectRestoreLocal)
    )

    // TODO[Backups]: localize
    private lazy var continueButton = choiceButton(
        title: "Continue without restoring",
        // comment: "The title for the device transfer 'choice' view 'transfer' option"
        body: "Don't attempt to restore, continue with a new instance.",
        // comment: "The body for the device transfer 'choice' view 'transfer' option"
        iconName: Theme.iconName(.register),
        selector: #selector(didSkipRestore)
    )

    public override func viewDidLoad() {
        super.viewDidLoad()
        initialRender()
    }

    public override func themeDidChange() {
        super.themeDidChange()
        render()
    }

    private func initialRender() {
        navigationItem.setHidesBackButton(true, animated: false)

        let scrollView = UIScrollView()
        view.addSubview(scrollView)
        scrollView.autoPinEdgesToSuperviewMargins()

        let stackView = UIStackView(arrangedSubviews: [
            titleLabel,
            explanationLabel,
            restoreFromBackupButton,
            continueButton,
            UIView.vStretchingSpacer()
        ])
        stackView.axis = .vertical
        stackView.distribution = .fill
        stackView.spacing = 16
        stackView.setCustomSpacing(12, after: titleLabel)
        stackView.setCustomSpacing(24, after: explanationLabel)
        scrollView.addSubview(stackView)
        stackView.autoPinWidth(toWidthOf: scrollView)
        stackView.autoPinHeightToSuperview()

        render()
    }

    private func render() {
        view.backgroundColor = Theme.backgroundColor
        titleLabel.textColor = .colorForRegistrationTitleLabel
        explanationLabel.textColor = .colorForRegistrationExplanationLabel
    }

    // MARK: Events

    @objc
    private func didSelectRestoreLocal() {
#if USE_DEBUG_UI && TESTABLE_BUILD
        if Platform.isSimulator {
            DebugUIMisc.debugOnly_savePlaintextDbKey()
        }
#endif

        let actionSheet = ActionSheetController(title: "Choose backup import source:")
        let localFileAction = ActionSheetAction(title: "Local backup") { [weak self] _ in
            self?.showMessageBackupPicker()
        }
        actionSheet.addAction(localFileAction)
        let remoteFileAction = ActionSheetAction(title: "Remote backup") { [weak self] _ in
            self?.presenter?.didSelectBackup(type: .remote)
        }
        actionSheet.addAction(remoteFileAction)
        presentActionSheet(actionSheet)
    }

    @objc
    private func didSkipRestore() {
        presenter?.skipRestoreFromBackup()
    }

    private func showMessageBackupPicker() {
        let vc = UIApplication.shared.frontmostViewController!
        let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.item], asCopy: false)
        documentPicker.delegate = self
        documentPicker.allowsMultipleSelection = false
        vc.present(documentPicker, animated: true)
    }
}

extension RegistrationRestoreFromBackupViewController: UIDocumentPickerDelegate {

    public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
        guard let fileUrl = urls.first else {
            return
        }
        presenter?.didSelectBackup(type: .local(fileUrl: fileUrl))
    }
}
