import UIKit

@MainActor
final class RepositoriesViewController: RefreshingTableViewController {
    private let context: AppContext
    private let mode: RepositoryPane
    private var rows: [RepositoryRow] = []
    private var currentPage: UInt32 = 0

    init(context: AppContext, mode: RepositoryPane) {
        self.context = context
        self.mode = mode
        super.init()
        title = context.core.activeServerName() ?? "Repositories"
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) { fatalError("init(coder:) is not supported") }

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.leftBarButtonItem = UIBarButtonItem(
            image: context.symbol("server.rack"),
            primaryAction: UIAction { [weak self] _ in
                guard let self else { return }
                self.navigationController?.pushViewController(
                    ServersViewController(context: self.context),
                    animated: true
                )
            }
        )
        loadContent(refreshing: false)
    }

    override func loadContent(refreshing: Bool) {
        loadPage(1, refreshing: refreshing)
    }

    override func loadMoreContent() {
        loadPage(currentPage + 1, refreshing: false)
    }

    private func loadPage(_ page: UInt32, refreshing: Bool) {
        if page == 1 {
            resetPagination()
            beginLoading(refreshing: refreshing)
        }
        loadingTask?.cancel()
        loadingTask = Task {
            do {
                let result = try await context.core.repositories(page: page, pane: mode)
                rows = result.rows
                currentPage = page
                finishPagination(hasMore: result.hasMore)
                tableView.reloadData()
                tableView.backgroundView = rows.isEmpty
                    ? EmptyBackgroundView(
                        title: "No repositories",
                        detail: "This account does not own any repositories on this server."
                    )
                    : nil
            } catch {
                if !Task.isCancelled {
                    show(error: error)
                    failPagination()
                }
            }
            if page == 1 { endLoading() }
        }
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        rows.count
    }

    override func tableView(
        _ tableView: UITableView,
        cellForRowAt indexPath: IndexPath
    ) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "repository")
            ?? UITableViewCell(style: .subtitle, reuseIdentifier: "repository")
        let row = rows[indexPath.row]
        configureTextCell(cell, title: row.name, detail: "\(row.description)\n\(row.meta)")
        let button = UIButton(type: .system, primaryAction: UIAction { [weak self] _ in
            self?.toggleFavorite(row)
        })
        button.setImage(context.symbol(row.favorite ? "star.fill" : "star"), for: .normal)
        button.tintColor = row.favorite ? .systemYellow : .tertiaryLabel
        button.frame.size = CGSize(width: 44, height: 44)
        cell.accessoryView = button
        return cell
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        96
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let row = rows[indexPath.row]
        let destination: UIViewController
        switch mode {
        case .issues:
            destination = IssuesViewController(
                context: context,
                owner: row.owner,
                repository: row.name
            )
        case .commits:
            destination = CommitsViewController(
                context: context,
                owner: row.owner,
                repository: row.name
            )
        case .milestones:
            destination = MilestonesViewController(
                context: context,
                owner: row.owner,
                repository: row.name
            )
        }
        navigationController?.pushViewController(destination, animated: true)
    }

    private func toggleFavorite(_ row: RepositoryRow) {
        do {
            rows = try context.core.toggleFavorite(
                owner: row.owner,
                repository: row.name,
                pane: mode
            )
            tableView.reloadData()
        } catch {
            show(error: error)
        }
    }
}
