//
//  ConferenceInvitationViewController.swift
//  TUIRoomKit
//
//  Created by jeremiawang on 2024/8/6.
//

import Foundation
import RTCRoomEngine
import UIKit
import Combine
import Factory

class ConferenceInvitationViewController: UIViewController {
    private var cancellableSet = Set<AnyCancellable>()
    var roomInfo: RoomInfo
    var invitation: TUIInvitation
    
    init(roomInfo: RoomInfo, invitation: TUIInvitation) {
        self.roomInfo = roomInfo
        self.invitation = invitation
        super.init(nibName: nil, bundle: nil)
        self.modalPresentationStyle = .fullScreen
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override public var shouldAutorotate: Bool {
        return false
    }
    
    override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
    
    private let backgroundImageView: UIImageView = {
        let view = UIImageView()
        view.contentMode = .scaleAspectFill
        view.alpha = 0.2
        return view
    }()
    
    private let avatarImageView: UIImageView = {
        let avatarImageView = UIImageView()
        avatarImageView.contentMode = .scaleAspectFill
        avatarImageView.layer.cornerRadius = 25
        avatarImageView.clipsToBounds = true
        return avatarImageView
    }()
    
    private let inviteLabel: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.font = UIFont(name: "PingFangSC-Regular", size: 14)
        return label
    }()
    
    private let conferenceNameLabel: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.font = UIFont.boldSystemFont(ofSize: 24)
        label.numberOfLines = 1
        label.lineBreakMode = .byTruncatingTail
        return label
    }()
    
    private let detailsLabel: UILabel = {
        let label = UILabel()
        label.textColor = .white
        label.font = UIFont(name: "PingFangSC-Regular", size: 14)
        return label
    }()
    
    private let joinSliderView: UIView = {
        let view = UIView()
        view.backgroundColor = .white.withAlphaComponent(0.1)
        view.layer.cornerRadius = 39.scale375()
        return view
    }()
    
    private let joinLabel: UILabel = {
        let label = UILabel()
        label.text = .joinNowText
        label.textColor = .white.withAlphaComponent(0.8)
        label.font = UIFont(name: "PingFangSC-Medium", size: 16)
        label.textAlignment = .center
        return label
    }()
    
    private let sliderThumbView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor.tui_color(withHex: "1C66E5")
        view.layer.cornerRadius = 32
        return view
    }()
    
    private let arrowImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(named: "room_rightlink_arrow", in: tuiRoomKitBundle(), compatibleWith: nil)
        imageView.tintColor = .white
        return imageView
    }()
    
    private let declineButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle(.notEnterText, for: .normal)
        button.setTitleColor(.white.withAlphaComponent(0.8), for: .normal)
        button.titleLabel?.font = UIFont(name: "PingFangSC-Medium", size: 16)
        return button
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .black
        initState()
        initializeData()
        constructViewHierarchy()
        activateConstraints()
        bindInteraction()
        operation.select(ViewSelectors.getDismissInvitationFlag)
            .receive(on: DispatchQueue.main)
            .removeDuplicates()
            .sink { [weak self] shouldDismissInvitation in
                guard let self = self else { return }
                if shouldDismissInvitation {
                    InvitationObserverService.shared.dismissInvitationWindow()
                }
            }
            .store(in: &cancellableSet)
    }
    
    deinit {
        debugPrint("deinit \(self)")
    }
    
    private func initState() {
        self.operation.dispatch(action: InvitationViewActions.resetInvitationFlag())
    }
    
    private func constructViewHierarchy() {
        view.addSubview(backgroundImageView)
        view.addSubview(avatarImageView)
        view.addSubview(inviteLabel)
        view.addSubview(conferenceNameLabel)
        view.addSubview(detailsLabel)
        view.addSubview(joinSliderView)
        joinSliderView.addSubview(joinLabel)
        joinSliderView.addSubview(sliderThumbView)
        sliderThumbView.addSubview(arrowImageView)
        view.addSubview(declineButton)
    }
    
    private func activateConstraints() {
        backgroundImageView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        avatarImageView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.height.width.equalTo(50.scale375())
            make.top.equalToSuperview().offset(150.scale375Height())
        }
        inviteLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(avatarImageView.snp.bottom).offset(16)
        }
        conferenceNameLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.width.lessThanOrEqualTo(300.scale375())
            make.top.equalTo(inviteLabel.snp.bottom).offset(30)
        }
        detailsLabel.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.top.equalTo(conferenceNameLabel.snp.bottom).offset(10)
        }
        declineButton.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.bottom.equalToSuperview().offset(-94.scale375Height())
        }
        joinSliderView.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.width.equalTo(200.scale375())
            make.height.equalTo(78.scale375())
            make.bottom.equalTo(declineButton.snp.top).offset(-30)
        }
        joinLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.centerX.equalToSuperview().offset(32.scale375())
        }
        sliderThumbView.snp.makeConstraints { make in
            make.left.equalTo(joinSliderView.snp.left).offset(5)
            make.centerY.equalTo(joinSliderView.snp.centerY)
            make.width.height.equalTo(64.scale375())
        }
        arrowImageView.snp.makeConstraints { make in
            make.center.equalTo(sliderThumbView)
            make.width.height.equalTo(20.scale375())
        }
    }
    
    private func bindInteraction() {
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:)))
        sliderThumbView.addGestureRecognizer(panGesture)
        declineButton.addTarget(self, action: #selector(rejectAction), for: .touchUpInside)
    }
    
    private func initializeData() {
        inviteLabel.text = invitation.inviter.userName + .inviteJoinConferenceText
        conferenceNameLabel.text = roomInfo.name
        detailsLabel.text = .hostText + roomInfo.ownerName + " | " + .participantText + String(roomInfo.memberCount)
        
        let placeholder = UIImage(named: "room_default_user", in: tuiRoomKitBundle(), compatibleWith: nil)
        if let url = URL(string: invitation.inviter.avatarUrl) {
            avatarImageView.sd_setImage(with: url, placeholderImage: placeholder)
            backgroundImageView.sd_setImage(with: url, placeholderImage: placeholder)
        } else {
            avatarImageView.image = placeholder
            backgroundImageView.image = placeholder
        }
    }
    
    @objc private func handlePanGesture(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: joinSliderView)
        let maxTranslation = joinSliderView.frame.width - sliderThumbView.frame.width - 10

        switch gesture.state {
            case .changed:
                if translation.x >= 0 && translation.x <= maxTranslation {
                    sliderThumbView.snp.updateConstraints { make in
                        make.left.equalTo(joinSliderView.snp.left).offset(5 + translation.x)
                    }
                }
            case .ended:
                if translation.x >= maxTranslation {
                    sliderThumbView.snp.updateConstraints { make in
                        make.left.equalTo(joinSliderView.snp.left).offset(5 + maxTranslation)
                    }
                    gesture.isEnabled = false
                    self.acceptAction()
                } else {
                    sliderThumbView.snp.updateConstraints { make in
                        make.left.equalTo(joinSliderView.snp.left).offset(5)
                    }
                    UIView.animate(withDuration: 0.3) {
                        self.view.layoutIfNeeded()
                    }
                }
            default:
                break
        }
    }
    
    private func acceptAction() {
        operation.dispatch(action: ConferenceInvitationActions.accept(payload: roomInfo.roomId))
    }
    
    @objc func rejectAction() {
        operation.dispatch(action: InvitationViewActions.dismissInvitationView())
        operation.dispatch(action: InvitationObserverActions.stopCallingBellAndVibration())
        operation.dispatch(action: ConferenceInvitationActions.reject(payload: (roomInfo.roomId, .rejectToEnter)))
    }
    
    @Injected(\.navigation) var route
    @Injected(\.conferenceStore) var operation
}

private extension String {
    static var inviteJoinConferenceText: String {
        localized(" invite you to join the conference")
    }
    static var hostText: String {
        localized("Conference Host")
    }
    static var participantText: String {
        localized("Participant")
    }
    static var peopleText: String {
        localized("People")
    }
    static var joinNowText: String {
        localized("Join now")
    }
    static var notEnterText: String {
        localized("Do not enter for now")
    }
}
