import UIKit

@MainActor
final class AppContext {
    let core = GotchaCore()
    private let window: UIWindow
    private(set) var tabs = UITabBarController()
    private(set) var navigationControllers: [UINavigationController] = []

    init(window: UIWindow) {
        self.window = window
        applyAppearance()
    }

    func makeRootController() -> UIViewController {
        let roots: [UIViewController] = [
            HomeViewController(context: self),
            repositoryRoot(mode: .issues),
            repositoryRoot(mode: .commits),
            PullsViewController(context: self),
            repositoryRoot(mode: .milestones),
        ]
        let items = [
            ("Home", "house", "house.fill"),
            ("Issues", "exclamationmark.circle", "exclamationmark.circle.fill"),
            ("Repos", "books.vertical", "books.vertical.fill"),
            ("PRs", "arrow.triangle.pull", "arrow.triangle.pull"),
            ("Milestones", "flag", "flag.fill"),
        ]
        navigationControllers = zip(roots, items).map { root, item in
            let navigation = UINavigationController(rootViewController: root)
            navigation.tabBarItem = UITabBarItem(
                title: item.0,
                image: UIImage(systemName: item.1),
                selectedImage: UIImage(systemName: item.2)
            )
            return navigation
        }
        tabs.viewControllers = navigationControllers
        return tabs
    }

    func showStartupErrorIfNeeded() {
        guard let message = core.startupError() else { return }
        tabs.present(errorAlert(message), animated: true)
    }

    func selectServer(index: UInt32) throws {
        try core.selectServer(index: index)
        let replacements: [(Int, UIViewController)] = [
            (0, HomeViewController(context: self)),
            (1, RepositoriesViewController(context: self, mode: .issues)),
            (2, RepositoriesViewController(context: self, mode: .commits)),
            (3, PullsViewController(context: self)),
            (4, RepositoriesViewController(context: self, mode: .milestones)),
        ]
        for (index, root) in replacements {
            navigationControllers[index].setViewControllers([root], animated: false)
        }
    }

    func didAddServer(index: UInt32) throws {
        try selectServer(index: index)
    }

    func applyAppearance() {
        switch core.settings().appearance {
        case 1: window.overrideUserInterfaceStyle = .light
        case 2: window.overrideUserInterfaceStyle = .dark
        default: window.overrideUserInterfaceStyle = .unspecified
        }
    }

    func route(_ activity: ActivityRow) {
        switch activity.target {
        case "repository":
            tabs.selectedIndex = 1
            navigationControllers[1].pushViewController(
                IssuesViewController(
                    context: self,
                    owner: activity.owner,
                    repository: activity.repository
                ),
                animated: true
            )
        case "issue":
            tabs.selectedIndex = 1
            navigationControllers[1].pushViewController(
                IssueViewController(
                    context: self,
                    owner: activity.owner,
                    repository: activity.repository,
                    number: activity.number
                ),
                animated: true
            )
        case "pull":
            tabs.selectedIndex = 3
            navigationControllers[3].pushViewController(
                PullViewController(
                    context: self,
                    owner: activity.owner,
                    repository: activity.repository,
                    number: activity.number
                ),
                animated: true
            )
        case "commit":
            tabs.selectedIndex = 2
            navigationControllers[2].pushViewController(
                FilesViewController(
                    context: self,
                    owner: activity.owner,
                    repository: activity.repository,
                    sha: activity.sha
                ),
                animated: true
            )
        default:
            break
        }
    }

    func symbol(_ name: String) -> UIImage? {
        UIImage(systemName: name)
    }

    private func repositoryRoot(mode: RepositoryMode) -> UIViewController {
        if core.activeServerIndex() == nil {
            return ServersViewController(context: self, destination: mode)
        }
        return RepositoriesViewController(context: self, mode: mode)
    }
}
