//
//  ScanViewController.swift
//  OrderScheduling
//
//  Created by 中道 on 2026/7/23.
//

import Foundation
import UIKit
import AVFoundation
import SnapKit
import DDAutoUIKit_Private
import DDControlsKit_Private
import DDToastKit_Private

class ScanViewController: ZDViewController {
    
    private lazy var session = AVCaptureSession()
    private var previewLayer: AVCaptureVideoPreviewLayer?
    private var scanCompletion: ((String?) -> Void)?
    
    private let scanRectView = UIView()
    private let tipLabel = UILabel()
    private let backButton = UIButton(type: .custom)
    private let torchButton = UIButton(type: .custom)
    
    init(completion: @escaping (String?) -> Void) {
        self.scanCompletion = completion
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        checkPermissionAndSetupCamera()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.navigationBar.isHidden = true
        if session.isRunning == false {
            DispatchQueue.global(qos: .background).async { [weak self] in
                self?.session.startRunning()
            }
        }
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.navigationBar.isHidden = false
        if session.isRunning == true {
            session.stopRunning()
        }
    }
    
    private func setupUI() {
        view.backgroundColor = .black
        
        scanRectView.layer.borderColor = UIColor.hex("00FF00").cgColor
        scanRectView.layer.borderWidth = 1.0
        view.addSubview(scanRectView)
        
        tipLabel.text = "将二维码/条码放入框内，即可自动扫描"
        tipLabel.textColor = .white
        tipLabel.font = UIFont.systemFont(ofSize: 14)
        tipLabel.textAlignment = .center
        view.addSubview(tipLabel)
        
        backButton.setImage(UIImage(named: "nav_back_white") ?? UIImage(systemName: "chevron.left"), for: .normal)
        backButton.tintColor = .white
        backButton.addTarget(self, action: #selector(backAction), for: .touchUpInside)
        view.addSubview(backButton)
        
        torchButton.setTitle("手电筒", for: .normal)
        torchButton.setTitleColor(.white, for: .normal)
        torchButton.titleLabel?.font = UIFont.systemFont(ofSize: 14)
        torchButton.addTarget(self, action: #selector(torchAction), for: .touchUpInside)
        view.addSubview(torchButton)
        
        scanRectView.snp.makeConstraints { make in
            make.center.equalToSuperview()
            make.width.height.equalTo(auto(260))
        }
        
        tipLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(scanRectView.snp.bottom).offset(auto(20))
            make.left.right.equalToSuperview().inset(auto(20))
        }
        
        backButton.snp.makeConstraints { make in
            make.top.equalTo(view.safeAreaLayoutGuide.snp.top).offset(auto(10))
            make.left.equalTo(auto(15))
            make.width.height.equalTo(auto(44))
        }
        
        torchButton.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(tipLabel.snp.bottom).offset(auto(30))
        }
    }
    
    private func checkPermissionAndSetupCamera() {
        let status = AVCaptureDevice.authorizationStatus(for: .video)
        switch status {
        case .authorized:
            setupCamera()
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
                DispatchQueue.main.async {
                    if granted {
                        self?.setupCamera()
                    } else {
                        self?.showPermissionAlert()
                    }
                }
            }
        default:
            showPermissionAlert()
        }
    }
    
    private func setupCamera() {
        guard let device = AVCaptureDevice.default(for: .video) else {
            showErrorAndBack("无法获取相机设备")
            return
        }
        
        do {
            let input = try AVCaptureDeviceInput(device: device)
            let output = AVCaptureMetadataOutput()
            output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            
            session.beginConfiguration()
            if session.canAddInput(input) {
                session.addInput(input)
            }
            if session.canAddOutput(output) {
                session.addOutput(output)
            }
            output.metadataObjectTypes = [.qr, .ean13, .ean8, .code128, .code39, .code93, .pdf417]
            session.commitConfiguration()
            
            let previewLayer = AVCaptureVideoPreviewLayer(session: session)
            previewLayer.videoGravity = .resizeAspectFill
            previewLayer.frame = view.bounds
            view.layer.insertSublayer(previewLayer, at: 0)
            self.previewLayer = previewLayer
            
            updateScanRect()
            
            DispatchQueue.global(qos: .background).async { [weak self] in
                self?.session.startRunning()
            }
        } catch {
            showErrorAndBack("相机初始化失败")
        }
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        previewLayer?.frame = view.bounds
        updateScanRect()
    }
    
    private func updateScanRect() {
        guard let previewLayer = previewLayer else { return }
        let rect = scanRectView.frame
        let scanRect = previewLayer.metadataOutputRectConverted(fromLayerRect: rect)
        if let output = session.outputs.first as? AVCaptureMetadataOutput {
            output.rectOfInterest = scanRect
        }
    }
    
    @objc private func backAction() {
        scanCompletion?(nil)
        navigationController?.popViewController(animated: true)
    }
    
    @objc private func torchAction() {
        guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
        do {
            try device.lockForConfiguration()
            device.torchMode = device.torchMode == .on ? .off : .on
            device.unlockForConfiguration()
        } catch {}
    }
    
    private func showPermissionAlert() {
        let alert = UIAlertController(title: "相机权限未开启", message: "请在设置中开启相机权限以使用扫码功能", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "取消", style: .cancel) { [weak self] _ in
            self?.scanCompletion?(nil)
            self?.navigationController?.popViewController(animated: true)
        })
        alert.addAction(UIAlertAction(title: "去设置", style: .default) { _ in
            if let url = URL(string: UIApplication.openSettingsURLString) {
                UIApplication.shared.open(url)
            }
        })
        present(alert, animated: true)
    }
    
    private func showErrorAndBack(_ message: String) {
        view.dd_makeToast(message)
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { [weak self] in
            self?.scanCompletion?(nil)
            self?.navigationController?.popViewController(animated: true)
        }
    }
}

extension ScanViewController: AVCaptureMetadataOutputObjectsDelegate {
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard let object = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
              let code = object.stringValue else { return }
        session.stopRunning()
        scanCompletion?(code)
        navigationController?.popViewController(animated: true)
    }
}
