//
//  ScheduleConferenceViewController.swift
//  TUIRoomKit
//
//  Created by janejntang on 2024/6/5.
//

import Foundation
import Factory
import RTCRoomEngine
import Combine
import TUICore

@objcMembers public class ScheduleConferenceViewController: UIViewController {
    private var cancellableSet = Set<AnyCancellable>()
    private let durationTime = 1800
    private let reminderSecondsBeforeStart = 600
    lazy var rootView: ScheduleConferenceTableView = {
        return ScheduleConferenceTableView(menus: ScheduleConferenceDataHelper.generateScheduleConferenceData(route: route, store: store, operation: operation, viewController: self))
    }()
    
    public override var shouldAutorotate: Bool {
        return false
    }
    
    public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
    
    public override func loadView() {
        self.view = rootView
    }
    
    public override func viewDidLoad() {
        super.viewDidLoad()
        initializeView()
        initializeRoute()
        initializeData()
        reportSchedulePanelShow()
        
        subscribeScheduleSubject()
        subscribeToast()
        
        let selector = Selector(keyPath: \ConferenceInfo.basicInfo.isPasswordEnabled)
        store.select(selector)
            .removeDuplicates()
            .receive(on: RunLoop.main)
            .sink { [weak self] isPasswordEnabled in
                guard let self = self else { return }
                var conferenceInfo = store.conferenceInfo
                conferenceInfo.basicInfo.password = isPasswordEnabled ? getRandomNumber(numberOfDigits: 6) : ""
                store.update(conference: conferenceInfo)
                self.rootView.menus = ScheduleConferenceDataHelper.generateScheduleConferenceData(route: self.route, store: self.store, operation: self.operation, viewController: self)
                self.rootView.tableView.reloadData()
            }
            .store(in: &cancellableSet)
    }
    
    private func initializeView() {
        view.backgroundColor = UIColor(0xF8F9FB)
        navigationItem.title = .bookRoomText
    }
    
    private func initializeRoute() {
        let viewRoute = ConferenceRoute.init(viewController: self)
        route.initializeRoute(viewController: self, rootRoute: viewRoute)
    }
    
    private func initializeData() {
        operation.dispatch(action: UserActions.getSelfInfo())
        getConferenceInfo { [weak self] conferenceInfo in
            guard let self = self else { return }
            self.store.update(conference: conferenceInfo)
            self.store.fetchAttendees(cursor: "")
        }
    }
    
    private func getConferenceInfo(onGetConferenceInfo: @escaping (ConferenceInfo)->()) {
        FetchRoomId.getRoomId { [weak self] roomId in
            guard let self = self else { return }
            var info = ConferenceInfo()
            info.scheduleStartTime = self.getStartTime()
            info.durationTime = UInt(self.durationTime)
            info.reminderSecondsBeforeStart = self.reminderSecondsBeforeStart
            var basicInfo = RoomInfo()
            basicInfo.roomId = roomId
            basicInfo.name = localizedReplace(.temporaryRoomText, replace: self.operation.selectCurrent(UserSelectors.getSelfUserName))
            basicInfo.isCameraDisableForAllUser = false
            basicInfo.isMicrophoneDisableForAllUser = false
            info.basicInfo = basicInfo
            onGetConferenceInfo(info)
        }
    }
    
    private func getStartTime() -> UInt {
        let oneMinutesInterval = 60
        let fiveMinutesInterval = UInt(5 * oneMinutesInterval)
        var time = UInt(Date().timeIntervalSince1970)
        let remainder = time % fiveMinutesInterval
        if  remainder > oneMinutesInterval {
            time = time - remainder
        }
        time = time + fiveMinutesInterval
        return time
    }
    
    private func getRandomNumber(numberOfDigits: Int) -> String {
        let minNumber = Int(truncating: NSDecimalNumber(decimal: pow(10, numberOfDigits - 1)))
        let maxNumber = Int(truncating: NSDecimalNumber(decimal: pow(10, numberOfDigits))) - 1
        let randomNumber = arc4random_uniform(UInt32(maxNumber - minNumber)) + UInt32(minNumber)
        return String(randomNumber)
    }
    
    private func reportSchedulePanelShow() {
        store.reportViewShow(dataReport: .metricsConferenceSchedulePanelShow)
    }
    
    deinit {
        debugPrint("deinit \(self)")
    }
    
    @Injected(\.navigation) private var route
    @Injected(\.modifyScheduleStore) private var store
    @Injected(\.conferenceStore) private var operation
}

extension ScheduleConferenceViewController {
    private func subscribeToast() {
        operation.toastSubject
            .receive(on: DispatchQueue.main)
            .sink { [weak self] toast in
                guard let self = self else { return }
                var position = TUICSToastPositionBottom
                switch toast.position {
                    case .center:
                        position = TUICSToastPositionCenter
                    default:
                        break
                }
                self.view.makeToast(toast.message, duration: toast.duration, position: position)
            }
            .store(in: &cancellableSet)
    }
    
    private func subscribeScheduleSubject() {
        operation.scheduleActionSubject
            .receive(on: RunLoop.main)
            .filter { $0.id == ScheduleResponseActions.onScheduleSuccess.id }
            .sink { [weak self] action in
                guard let self = self else { return }
                self.route.pop()
            }
            .store(in: &cancellableSet)
    }
}

extension ScheduleConferenceViewController: ContactViewSelectDelegate {
    public func onMemberSelected(_ viewController: ContactViewProtocol, 
                                 invitees: [User]) {
        var conferenceInfo = store.conferenceInfo
        conferenceInfo.attendeeListResult.attendeeList = invitees.map { $0.userInfo }
        conferenceInfo.attendeeListResult.totalCount = UInt(invitees.count)
        store.update(conference: conferenceInfo)
        route.pop()
    }
}

private extension String {
    static var bookRoomText: String = localized("Schedule Room")
    static var temporaryRoomText: String = localized("xx's temporary room")
}
