//
//  ProfileSpaceSettingsDialogs.swift
//  suixinkan
//

import SnapKit
import UIKit

/// 空间设置使用的 Android 风格图标集合。
enum ProfileSpaceIcon {
    /// 蓝色 16pt 编辑图标。
    static var edit: UIImage? {
        UIImage(named: "profile_edit")
    }
}

/// 空间设置链路使用的 Android 风格导航栏外观。
enum ProfileNavigationStyle {
    static func apply(to navigationController: UINavigationController?, showsDivider: Bool) {
        guard let navigationBar = navigationController?.navigationBar else { return }
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = .white
        appearance.shadowColor = showsDivider ? AppColor.border : .clear
        appearance.titleTextAttributes = [
            .foregroundColor: UIColor(hex: 0x333333),
            .font: UIFont.systemFont(ofSize: 18),
        ]
        navigationBar.standardAppearance = appearance
        navigationBar.scrollEdgeAppearance = appearance
        navigationBar.compactAppearance = appearance
        navigationBar.tintColor = .black
    }

    static func restore(_ navigationController: UINavigationController?) {
        guard let navigationBar = navigationController?.navigationBar else { return }
        let appearance = UINavigationBarAppearance()
        appearance.configureWithOpaqueBackground()
        appearance.backgroundColor = AppColor.cardBackground
        appearance.shadowColor = .clear
        appearance.titleTextAttributes = [
            .foregroundColor: AppColor.textPrimary,
            .font: UIFont.app(.title),
        ]
        navigationBar.standardAppearance = appearance
        navigationBar.scrollEdgeAppearance = appearance
        navigationBar.compactAppearance = appearance
        navigationBar.tintColor = AppColor.primary
    }
}

/// 绘制 Android 风格虚线边框的按钮。
final class ProfileDashedBorderButton: UIButton {
    private let dashedLayer = CAShapeLayer()

    override init(frame: CGRect) {
        super.init(frame: frame)
        dashedLayer.strokeColor = AppColor.primary.cgColor
        dashedLayer.fillColor = UIColor.clear.cgColor
        dashedLayer.lineWidth = 1
        dashedLayer.lineDashPattern = [2, 2]
        layer.addSublayer(dashedLayer)
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        dashedLayer.frame = bounds
        dashedLayer.path = UIBezierPath(roundedRect: bounds.insetBy(dx: 0.5, dy: 0.5), cornerRadius: 4).cgPath
    }

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        bounds.insetBy(dx: -8, dy: -8).contains(point)
    }
}

/// Android 风格弹窗基类，提供遮罩、白色卡片和无动画关闭能力。
class ProfileBaseDialogViewController: UIViewController {
    let cardView = UIView()

    init() {
        super.init(nibName: nil, bundle: nil)
        modalPresentationStyle = .overFullScreen
        modalTransitionStyle = .crossDissolve
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.black.withAlphaComponent(0.2)
        cardView.backgroundColor = .white
        view.addSubview(cardView)
        let outsideTap = UITapGestureRecognizer(target: self, action: #selector(outsideTapped(_:)))
        outsideTap.cancelsTouchesInView = false
        view.addGestureRecognizer(outsideTap)
        cardView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.leading.trailing.equalToSuperview().inset(32)
        }
    }

    func makePrimaryButton(title: String, height: CGFloat = 45) -> UIButton {
        let button = UIButton(type: .system)
        button.setTitle(title, for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.setTitleColor(.white, for: .disabled)
        button.titleLabel?.font = .systemFont(ofSize: 17, weight: .medium)
        button.backgroundColor = AppColor.primary
        button.layer.cornerRadius = 10
        button.snp.makeConstraints { make in make.height.equalTo(height) }
        return button
    }

    @objc private func outsideTapped(_ gesture: UITapGestureRecognizer) {
        let location = gesture.location(in: view)
        guard !cardView.frame.contains(location) else { return }
        dismiss(animated: false)
    }
}

/// Android 风格时间滚轮弹窗。
final class ProfileTimePickerDialogViewController: ProfileBaseDialogViewController {
    private let picker = UIDatePicker()
    private let confirmButton: UIButton
    private let onConfirm: (Date) -> Void

    init(initialDate: Date, onConfirm: @escaping (Date) -> Void) {
        self.onConfirm = onConfirm
        confirmButton = UIButton(type: .system)
        super.init()
        picker.date = initialDate
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        cardView.layer.cornerRadius = 10
        picker.datePickerMode = .time
        picker.preferredDatePickerStyle = .wheels
        picker.locale = Locale(identifier: "zh_CN")

        confirmButton.setTitle("确认", for: .normal)
        confirmButton.setTitleColor(.white, for: .normal)
        confirmButton.titleLabel?.font = .systemFont(ofSize: 17, weight: .medium)
        confirmButton.backgroundColor = AppColor.primary
        confirmButton.layer.cornerRadius = 10
        confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)

        cardView.addSubview(picker)
        cardView.addSubview(confirmButton)
        picker.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(24)
            make.leading.trailing.equalToSuperview().inset(15)
            make.height.equalTo(180)
        }
        confirmButton.snp.makeConstraints { make in
            make.top.equalTo(picker.snp.bottom).offset(24)
            make.leading.trailing.equalToSuperview().inset(15)
            make.height.equalTo(45)
            make.bottom.equalToSuperview().inset(24)
        }
    }

    @objc private func confirmTapped() {
        onConfirm(picker.date)
        dismiss(animated: false)
    }
}

/// Android 风格相机设备输入弹窗。
final class ProfileDeviceDialogViewController: ProfileBaseDialogViewController, UITextFieldDelegate {
    private let textField = UITextField()
    private let confirmButton = UIButton(type: .system)
    private let onConfirm: (String) -> Void

    init(onConfirm: @escaping (String) -> Void) {
        self.onConfirm = onConfirm
        super.init()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        cardView.layer.cornerRadius = 10
        textField.placeholder = "请输入设备名"
        textField.font = .systemFont(ofSize: 14)
        textField.layer.borderColor = AppColor.border.cgColor
        textField.layer.borderWidth = 1
        textField.layer.cornerRadius = 8
        textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: 1))
        textField.leftViewMode = .always
        textField.returnKeyType = .done
        textField.delegate = self
        textField.addTarget(self, action: #selector(textChanged), for: .editingChanged)

        confirmButton.setTitle("确认", for: .normal)
        confirmButton.setTitleColor(.white, for: .normal)
        confirmButton.setTitleColor(.white, for: .disabled)
        confirmButton.titleLabel?.font = .systemFont(ofSize: 17, weight: .medium)
        confirmButton.layer.cornerRadius = 10
        confirmButton.isEnabled = false
        confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)

        cardView.addSubview(textField)
        cardView.addSubview(confirmButton)
        textField.snp.makeConstraints { make in
            make.top.equalToSuperview().offset(24)
            make.leading.trailing.equalToSuperview().inset(15)
            make.height.equalTo(46)
        }
        confirmButton.snp.makeConstraints { make in
            make.top.equalTo(textField.snp.bottom).offset(24)
            make.leading.trailing.equalToSuperview().inset(15)
            make.height.equalTo(45)
            make.bottom.equalToSuperview().inset(24)
        }
        textChanged()
        DispatchQueue.main.async { [weak self] in self?.textField.becomeFirstResponder() }
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        guard confirmButton.isEnabled else { return false }
        confirmTapped()
        return true
    }

    @objc private func textChanged() {
        let enabled = !(textField.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
        confirmButton.isEnabled = enabled
        confirmButton.backgroundColor = enabled ? AppColor.primary : AppColor.buttonDisabled
    }

    @objc private func confirmTapped() {
        let value = (textField.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
        guard !value.isEmpty else { return }
        onConfirm(value)
        dismiss(animated: false)
    }
}

/// Android 风格红色删除确认弹窗。
final class ProfileDeleteDialogViewController: ProfileBaseDialogViewController {
    private let dialogTitle: String
    private let dialogMessage: String
    private let onConfirm: () -> Void

    init(title: String, message: String, onConfirm: @escaping () -> Void) {
        dialogTitle = title
        dialogMessage = message
        self.onConfirm = onConfirm
        super.init()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        cardView.layer.cornerRadius = 16
        let stack = UIStackView()
        stack.axis = .vertical
        stack.spacing = 16
        stack.layoutMargins = UIEdgeInsets(top: 24, left: 24, bottom: 24, right: 24)
        stack.isLayoutMarginsRelativeArrangement = true

        let titleLabel = UILabel()
        titleLabel.text = dialogTitle
        titleLabel.font = .systemFont(ofSize: 18, weight: .bold)
        titleLabel.textColor = UIColor(hex: 0xFF0000)
        let messageLabel = UILabel()
        messageLabel.font = .systemFont(ofSize: 16)
        messageLabel.textColor = UIColor(hex: 0x333333)
        messageLabel.numberOfLines = 0
        let message = NSMutableAttributedString(
            string: dialogMessage,
            attributes: [.font: UIFont.systemFont(ofSize: 16), .foregroundColor: UIColor(hex: 0x333333)]
        )
        let prefix = "您确定要删除"
        if dialogMessage.hasPrefix(prefix), dialogTitle != "删除日程" {
            let suffixes = ["标签吗?", "拍摄说明吗?", "设备吗?"]
            if let suffix = suffixes.first(where: dialogMessage.hasSuffix) {
                let nameStart = prefix.count
                let nameLength = dialogMessage.count - prefix.count - suffix.count
                if nameLength > 0 {
                    message.addAttribute(.font, value: UIFont.systemFont(ofSize: 16, weight: .bold), range: NSRange(location: nameStart, length: nameLength))
                }
            }
        }
        messageLabel.attributedText = message

        let buttons = UIStackView()
        buttons.axis = .horizontal
        buttons.spacing = 12
        buttons.distribution = .fillEqually
        let cancel = UIButton(type: .system)
        cancel.setTitle("取消", for: .normal)
        cancel.setTitleColor(UIColor(hex: 0xFF0000), for: .normal)
        cancel.backgroundColor = UIColor(hex: 0xFFE5E5)
        cancel.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        cancel.layer.cornerRadius = 8
        cancel.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
        let confirm = UIButton(type: .system)
        confirm.setTitle("确认", for: .normal)
        confirm.setTitleColor(.white, for: .normal)
        confirm.backgroundColor = UIColor(hex: 0xFF0000)
        confirm.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        confirm.layer.cornerRadius = 8
        confirm.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
        [cancel, confirm].forEach { button in
            button.snp.makeConstraints { make in make.height.equalTo(44) }
            buttons.addArrangedSubview(button)
        }

        stack.addArrangedSubview(titleLabel)
        stack.addArrangedSubview(messageLabel)
        stack.setCustomSpacing(24, after: messageLabel)
        stack.addArrangedSubview(buttons)
        cardView.addSubview(stack)
        stack.snp.makeConstraints { make in make.edges.equalToSuperview() }
    }

    @objc private func cancelTapped() { dismiss(animated: false) }

    @objc private func confirmTapped() {
        dismiss(animated: false) { [onConfirm] in onConfirm() }
    }
}

/// 支持缩放和平移的正方形头像裁剪页面，输出 Android 要求的 480×480 JPEG。
final class ProfileAvatarCropViewController: UIViewController, UIScrollViewDelegate {
    private let sourceImage: UIImage
    private let onConfirm: (Data) -> Void
    private let scrollView = UIScrollView()
    private let imageView = UIImageView()
    private let cancelButton = UIButton(type: .system)
    private let confirmButton = UIButton(type: .system)
    private var didConfigureZoom = false

    init(image: UIImage, onConfirm: @escaping (Data) -> Void) {
        sourceImage = Self.normalized(image)
        self.onConfirm = onConfirm
        super.init(nibName: nil, bundle: nil)
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        scrollView.delegate = self
        scrollView.clipsToBounds = true
        scrollView.layer.borderColor = UIColor.white.cgColor
        scrollView.layer.borderWidth = 1
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.showsVerticalScrollIndicator = false
        imageView.image = sourceImage
        imageView.contentMode = .scaleAspectFit
        imageView.frame = CGRect(origin: .zero, size: sourceImage.size)
        scrollView.addSubview(imageView)
        scrollView.contentSize = sourceImage.size

        cancelButton.setTitle("取消", for: .normal)
        confirmButton.setTitle("确认", for: .normal)
        [cancelButton, confirmButton].forEach {
            $0.setTitleColor(.white, for: .normal)
            $0.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
        }
        cancelButton.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
        confirmButton.addTarget(self, action: #selector(confirmTapped), for: .touchUpInside)
        view.addSubview(scrollView)
        view.addSubview(cancelButton)
        view.addSubview(confirmButton)
        scrollView.snp.makeConstraints { make in
            make.leading.trailing.equalToSuperview()
            make.centerY.equalToSuperview()
            make.height.equalTo(scrollView.snp.width)
        }
        cancelButton.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(20)
            make.top.equalTo(view.safeAreaLayoutGuide).offset(10)
            make.width.height.greaterThanOrEqualTo(44)
        }
        confirmButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview().inset(20)
            make.top.equalTo(view.safeAreaLayoutGuide).offset(10)
            make.width.height.greaterThanOrEqualTo(44)
        }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        guard !didConfigureZoom, scrollView.bounds.width > 0 else { return }
        didConfigureZoom = true
        let minimumZoom = max(
            scrollView.bounds.width / sourceImage.size.width,
            scrollView.bounds.height / sourceImage.size.height
        )
        scrollView.minimumZoomScale = minimumZoom
        scrollView.maximumZoomScale = max(minimumZoom * 6, 6)
        scrollView.zoomScale = minimumZoom
        let contentWidth = sourceImage.size.width * minimumZoom
        let contentHeight = sourceImage.size.height * minimumZoom
        scrollView.contentOffset = CGPoint(
            x: max(0, (contentWidth - scrollView.bounds.width) / 2),
            y: max(0, (contentHeight - scrollView.bounds.height) / 2)
        )
    }

    func viewForZooming(in scrollView: UIScrollView) -> UIView? { imageView }

    @objc private func cancelTapped() { dismiss(animated: true) }

    @objc private func confirmTapped() {
        guard let data = renderedCropData() else { return }
        dismiss(animated: true) { [onConfirm] in onConfirm(data) }
    }

    func renderedCropData() -> Data? {
        let cropRectInImageView = scrollView.convert(scrollView.bounds, to: imageView)
        let scaleX = sourceImage.size.width / imageView.bounds.width
        let scaleY = sourceImage.size.height / imageView.bounds.height
        var cropRect = CGRect(
            x: cropRectInImageView.minX * scaleX,
            y: cropRectInImageView.minY * scaleY,
            width: cropRectInImageView.width * scaleX,
            height: cropRectInImageView.height * scaleY
        ).integral
        cropRect = cropRect.intersection(CGRect(origin: .zero, size: sourceImage.size))
        guard !cropRect.isEmpty, let cgImage = sourceImage.cgImage?.cropping(to: cropRect) else { return nil }
        let cropped = UIImage(cgImage: cgImage)
        let renderer = UIGraphicsImageRenderer(size: CGSize(width: 480, height: 480))
        return renderer.image { _ in
            cropped.draw(in: CGRect(x: 0, y: 0, width: 480, height: 480))
        }.jpegData(compressionQuality: 0.9)
    }

    private static func normalized(_ image: UIImage) -> UIImage {
        guard image.imageOrientation != .up else { return image }
        let renderer = UIGraphicsImageRenderer(size: image.size)
        return renderer.image { _ in image.draw(in: CGRect(origin: .zero, size: image.size)) }
    }
}
