//
//  QRCodeScannerViewController.swift
//  suixinkan
//

import AVFoundation
import SnapKit
import UIKit

/// AVFoundation 二维码扫描页。
final class QRCodeScannerViewController: BaseViewController, AVCaptureMetadataOutputObjectsDelegate {

    var onScanResult: ((String) -> Void)?

    private let captureSession = AVCaptureSession()
    private var previewLayer: AVCaptureVideoPreviewLayer?
    private var isCameraConfigured = false
    private var hasHandledResult = false

    private let maskView = UIView()
    private let hintLabel = UILabel()
    private let closeButton = UIButton(type: .system)

    override func setupNavigationBar() {
        navigationController?.setNavigationBarHidden(true, animated: false)
    }

    override func setupUI() {
        view.backgroundColor = .black
        hintLabel.text = "将二维码放入框内"
        hintLabel.textColor = .white
        hintLabel.font = .systemFont(ofSize: 14)
        hintLabel.textAlignment = .center

        closeButton.setTitle("关闭", for: .normal)
        closeButton.setTitleColor(.white, for: .normal)
        closeButton.addTarget(self, action: #selector(closeTapped), for: .touchUpInside)

        view.addSubview(maskView)
        view.addSubview(hintLabel)
        view.addSubview(closeButton)
    }

    override func setupConstraints() {
        closeButton.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide).offset(12)
            make.trailing.equalToSuperview().inset(16)
        }
        hintLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalTo(view.safeAreaLayoutGuide).inset(48)
        }
        maskView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.size.equalTo(260)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        checkCameraPermission()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        updatePreviewLayout()
        startCaptureSessionIfNeeded()
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        updatePreviewLayout()
        updateMask()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        stopCaptureSession()
    }

    private func checkCameraPermission() {
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .authorized:
            setupCamera()
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
                DispatchQueue.main.async {
                    granted ? self?.setupCamera() : self?.showPermissionDenied()
                }
            }
        default:
            showPermissionDenied()
        }
    }

    private func showPermissionDenied() {
        showToast("需要相机权限才能扫码")
        dismiss(animated: true)
    }

    private func setupCamera() {
        if isCameraConfigured {
            updatePreviewLayout()
            startCaptureSessionIfNeeded()
            return
        }

        guard let device = AVCaptureDevice.default(for: .video),
              let input = try? AVCaptureDeviceInput(device: device) else {
            showToast("无法打开相机")
            return
        }

        captureSession.beginConfiguration()
        defer { captureSession.commitConfiguration() }

        guard captureSession.canAddInput(input) else { return }
        captureSession.addInput(input)

        let output = AVCaptureMetadataOutput()
        guard captureSession.canAddOutput(output) else { return }
        captureSession.addOutput(output)
        output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        output.metadataObjectTypes = [.qr]

        let layer = AVCaptureVideoPreviewLayer(session: captureSession)
        layer.videoGravity = .resizeAspectFill
        view.layer.insertSublayer(layer, at: 0)
        previewLayer = layer
        isCameraConfigured = true

        updatePreviewLayout()
        startCaptureSessionIfNeeded()
    }

    private func updatePreviewLayout() {
        previewLayer?.frame = view.bounds
    }

    private func startCaptureSessionIfNeeded() {
        guard isCameraConfigured, !captureSession.isRunning else { return }
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            self?.captureSession.startRunning()
        }
    }

    private func stopCaptureSession() {
        guard captureSession.isRunning else { return }
        DispatchQueue.global(qos: .userInitiated).async { [weak self] in
            self?.captureSession.stopRunning()
        }
    }

    private func updateMask() {
        maskView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
        let border = CAShapeLayer()
        border.path = UIBezierPath(roundedRect: maskView.bounds, cornerRadius: 12).cgPath
        border.strokeColor = AppColor.primary.cgColor
        border.fillColor = UIColor.clear.cgColor
        border.lineWidth = 2
        maskView.layer.addSublayer(border)
    }

    func metadataOutput(
        _ output: AVCaptureMetadataOutput,
        didOutput metadataObjects: [AVMetadataObject],
        from connection: AVCaptureConnection
    ) {
        guard !hasHandledResult,
              let object = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
              object.type == .qr,
              let value = object.stringValue,
              !value.isEmpty else { return }
        hasHandledResult = true
        stopCaptureSession()
        onScanResult?(value)
        dismiss(animated: true)
    }

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