//
//  LNImageFeedDetailViewController.swift
//  Gami
//
//  Created by OneeChan on 2026/3/3.
//

import Foundation
import UIKit
import SnapKit
import MJRefresh


extension UIView {
    func pushToImageFeedDetail(id: String) {
        let vc = LNImageFeedDetailViewController()
        vc.loadDetail(id: id)
        navigationController?.pushViewController(vc, animated: true)
    }
}


class LNImageFeedDetailViewController: LNViewController {
    private let avatar = UIImageView()
    private let nameLabel = UILabel()
    
    private let tableView = UITableView(frame: .zero, style: .grouped)
    
    private let likeView = LNFeedLikeView()
    private let commentView = LNFeedCommentView()
    
    private var curDetail: LNFeedDetailVO?
    private var nextTag: String?
    private var comments: [LNFeedCommentVO] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupViews()
    }
    
    func loadDetail(id: String) {
        LNFeedManager.shared.getFeedDetail(id: id) { [weak self] detail in
            guard let self else { return }
            guard let detail else {
                navigationController?.popViewController(animated: true)
                return
            }
            
            curDetail = detail
            tableView.reloadData()
            
            avatar.sd_setImage(with: URL(string: detail.avatar))
            nameLabel.text = detail.nickname
            likeView.update(id: id, liked: detail.liked, count: detail.likeCount)
            commentView.update(id: id, count: detail.commentCount)
        }
        nextTag = nil
        loadComment(id: id)
    }
}

extension LNImageFeedDetailViewController {
    private func loadComment(id: String) {
        LNFeedManager.shared.getFeedCommentList(id: id, next: nextTag) { [weak self] res in
            guard let self else { return }
            if let res {
                if nextTag?.isEmpty != false {
                    comments.removeAll()
                    tableView.mj_header?.endRefreshing()
                }
                comments.append(contentsOf: res.list)
                self.nextTag = nextTag
                tableView.reloadData()
            }
            
            if nextTag?.isEmpty != false {
                tableView.mj_footer?.endRefreshingWithNoMoreData()
            } else {
                tableView.mj_footer?.endRefreshing()
            }
        }
    }
    
    private func toComment(checkScroll: Bool = true) {
        guard let curDetail else { return }
        if checkScroll, !scrollToComment() {
            return
        }
        
        let panel = LNCommonInputPanel()
        panel.maxInput = LNFeedManager.feedCommentMaxInput
        panel.handler = { [weak self] comment in
            guard let self else { return }
            LNFeedManager.shared.sendFeedComment(id: curDetail.id, content: comment) { [weak self] success in
                guard let self else { return }
                guard success else { return }
                
                let item = LNFeedCommentVO()
                item.avatar = myUserInfo.avatar
                item.nickname = myUserInfo.nickname
                item.textContent = comment
                item.createdAt = Int(curTime * 1_000)
                comments.insert(item, at: 0)
                tableView.reloadSections(.init(integer: 1), with: .automatic)
                
                curDetail.commentCount += 1
                LNFeedManager.shared.notifyFeedCommentChanged(id: curDetail.id, count: curDetail.commentCount)
            }
        }
        panel.popup()
    }
}

extension LNImageFeedDetailViewController: UITableViewDataSource, UITableViewDelegate {
    func numberOfSections(in tableView: UITableView) -> Int {
        2
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if section == 0 {
            1
        } else {
            comments.count
        }
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: LNImageFeedHeaderCell.className, for: indexPath) as! LNImageFeedHeaderCell
            cell.update(curDetail)
            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: LNFeedCommentCell.className, for: indexPath) as! LNFeedCommentCell
            cell.update(comments[indexPath.row])
            return cell
        }
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        if section == 0 {
            0
        } else {
            36
        }
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        if section == 0 {
            return nil
        }
        let container = UIView()
        
        let titleLabel = UILabel()
        titleLabel.font = .body_m
        titleLabel.textColor = .text_5
        titleLabel.text = .init(key: "A00304", comments.count)
        container.addSubview(titleLabel)
        titleLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
        }
        
        return container
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        0
    }
    
    func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        nil
    }
}

extension LNImageFeedDetailViewController {
    private func scrollToComment() -> Bool {
        if curDetail?.commentCount == 0 {
            return true
        }
        if tableView.contentOffset.y
            + tableView.bounds.height
            + tableView.contentInset.top
            > tableView.contentSize.height - 50 {
            return true
        }
        
        let rect = tableView.rectForHeader(inSection: 1)
        let convertedRect = tableView.convert(rect, to: tableView.superview)
        
        if convertedRect.minY - 50 <= tableView.bounds.minY + tableView.contentInset.top {
            return true
        }
        
        let indexPath = IndexPath(row: 0, section: 1)
        tableView.scrollToRow(at: indexPath, at: .top, animated: true)
        return false
    }
    
    private func setupViews() {
        setupNavBar()
        
        let bottomMenu = buildMenuView()
        view.addSubview(bottomMenu)
        bottomMenu.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.bottom.equalTo(view.safeAreaLayoutGuide.snp.bottom)
        }
        
        let listView = buildListView()
        view.addSubview(listView)
        listView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.top.equalToSuperview()
            make.bottom.equalTo(bottomMenu.snp.top)
        }
    }
    
    private func setupNavBar() {
        let menu = buildButtonMenu()
        setRightButton(menu)
        
        let container = UIView()
        avatar.layer.cornerRadius = 16
        avatar.clipsToBounds = true
        container.addSubview(avatar)
        avatar.snp.makeConstraints { make in
            make.leading.equalToSuperview()
            make.centerY.equalToSuperview()
            make.width.height.equalTo(32)
        }
        
        nameLabel.font = .heading_h3
        nameLabel.textColor = .text_5
        nameLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
        nameLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        container.addSubview(nameLabel)
        nameLabel.snp.makeConstraints { make in
            make.leading.equalTo(avatar.snp.trailing).offset(12)
            make.centerY.equalToSuperview()
            make.trailing.lessThanOrEqualToSuperview().offset(-37)
        }
        
        setTitleView(container)
        container.snp.makeConstraints { make in
            make.width.equalTo(view.bounds.width).priority(.medium)
            make.height.equalTo(44)
        }
    }
    
    private func buildButtonMenu() -> UIView {
        let moreButton = UIButton()
        moreButton.setImage(.icMoreFull, for: .normal)
        moreButton.snp.makeConstraints { make in
            make.width.height.equalTo(32)
        }
        moreButton.addAction(UIAction(handler: { [weak self] _ in
            guard let self else { return }
            guard let curDetail else { return }
            LNBottomSheetMenu.showFeedMenu(detail: curDetail, view: view)
        }), for: .touchUpInside)
        
        return moreButton
    }
    
    private func buildMenuView() -> UIView {
        let container = UIView()
        container.snp.makeConstraints { make in
            make.height.equalTo(58)
        }
        
        let comment = buildComment()
        container.addSubview(comment)
        comment.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.trailing.equalToSuperview().offset(-16)
        }
        
        let like = buildLike()
        container.addSubview(like)
        like.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.trailing.equalTo(comment.snp.leading).offset(-20)
        }
        
        let input = buildInput()
        container.addSubview(input)
        input.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalToSuperview().offset(16)
            make.width.equalTo(190)
        }
        
        return container
    }
    
    private func buildComment() -> UIView {
        commentView.uiColor = .text_4
        commentView.onTap { [weak self] in
            guard let self else { return }
            toComment()
        }
        
        return commentView
    }
    
    private func buildLike() -> UIView {
        likeView.uiColor = .text_4
        
        return likeView
    }
    
    private func buildInput() -> UIView {
        let container = UIView()
        container.backgroundColor = .fill_2
        container.layer.cornerRadius = 19
        container.onTap { [weak self] in
            guard let self else { return }
            toComment(checkScroll: false)
        }
        container.snp.makeConstraints { make in
            make.height.equalTo(38)
        }
        
        let editIc = UIImageView()
        editIc.image = .icImChatMenuRemark.withTintColor(.text_2)
        container.addSubview(editIc)
        editIc.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(10)
            make.centerY.equalToSuperview()
            make.width.height.equalTo(24)
        }
        
        let tipsLabel = UILabel()
        tipsLabel.font = .body_m
        tipsLabel.textColor = .text_2
        tipsLabel.text = .init(key: "A00300")
        container.addSubview(tipsLabel)
        tipsLabel.snp.makeConstraints { make in
            make.centerY.equalToSuperview()
            make.leading.equalTo(editIc.snp.trailing).offset(4)
            make.trailing.equalToSuperview().offset(-10)
        }
        
        return container
    }
    
    private func buildListView() -> UIView {
        tableView.register(LNFeedCommentCell.self, forCellReuseIdentifier: LNFeedCommentCell.className)
        tableView.register(LNImageFeedHeaderCell.self, forCellReuseIdentifier: LNImageFeedHeaderCell.className)
        tableView.showsVerticalScrollIndicator = false
        tableView.showsHorizontalScrollIndicator = false
        tableView.backgroundColor = .clear
        tableView.separatorStyle = .none
        tableView.dataSource = self
        tableView.delegate = self
        tableView.allowsSelection = false
        
        let header = MJRefreshNormalHeader { [weak self] in
            guard let self else { return }
            guard let curDetail else { return }
            self.nextTag = nil
            self.loadDetail(id: curDetail.id)
        }
        header.lastUpdatedTimeLabel?.isHidden = true
        header.stateLabel?.isHidden = true
        tableView.mj_header = header
        
        let footer = MJRefreshAutoNormalFooter { [weak self] in
            guard let self else { return }
            guard let curDetail else { return }
            self.loadComment(id: curDetail.id)
        }
        footer.setTitle("", for: .noMoreData)
        footer.setTitle(.init(key: "A00046"), for: .idle)
        tableView.mj_footer = footer
        
        return tableView
    }
}

private class LNImageFeedHeaderCell: UITableViewCell {
    private let stackView = UIStackView()
    private let pageControl = UIPageControl()
    private let contentLabel = UILabel()
    private let timeLabel = UILabel()
    private var curImageUrls: [String] = []
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        setupViews()
    }
    
    func update(_ detail: LNFeedDetailVO?) {
        contentLabel.text = detail?.textContent
        contentLabel.superview?.isHidden = detail?.textContent.isEmpty != false
        timeLabel.text = TimeInterval((detail?.createdAt ?? 0) / 1_000).tencentIMTimeDesc
        
        let urls = detail?.medias.compactMap { $0.type == .image ? $0.url : nil} ?? []
        if urls == curImageUrls {
            return
        }
        curImageUrls = urls
        
        if urls.isEmpty {
            stackView.superview?.isHidden = true
            pageControl.superview?.isHidden = true
            return
        }
        
        stackView.arrangedSubviews.forEach {
            stackView.removeArrangedSubview($0)
            $0.removeFromSuperview()
        }
        stackView.superview?.isHidden = false
        
        let size = urls[0].extractSize
        let scale = (size.height / size.width).bounded(min: 169.0/375.0, max: 4.0/3.0)
        
        for (index, url) in urls.enumerated() {
            let imageView = buildImageView()
            imageView.sd_setImage(with: URL(string: url))
            imageView.onTap { [weak self] in
                guard let self else { return }
                presentImagePreview(urls, index)
            }
            stackView.addArrangedSubview(imageView)
            if index == 0 {
                imageView.snp.makeConstraints { make in
                    make.width.equalTo(stackView.superview!)
                    make.height.equalTo(imageView.snp.width).multipliedBy(scale)
                }
            }
        }
        
        pageControl.numberOfPages = urls.count
        pageControl.superview?.isHidden = false
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension LNImageFeedHeaderCell: UIScrollViewDelegate {
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        checkPageIndex(scrollView)
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        checkPageIndex(scrollView)
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        checkPageIndex(scrollView)
    }
}

extension LNImageFeedHeaderCell {
    private func checkPageIndex(_ scrollView: UIScrollView) {
        let page = scrollView.contentOffset.x / scrollView.bounds.width
        pageControl.currentPage = Int(page)
    }
    
    private func setupViews() {
        let stackView = UIStackView()
        stackView.axis = .vertical
        stackView.spacing = 8
        contentView.addSubview(stackView)
        stackView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.top.equalToSuperview()
        }
        
        stackView.addArrangedSubview(buildAlbum())
        stackView.addArrangedSubview(buildPage())
        stackView.addArrangedSubview(buildContent())
        stackView.addArrangedSubview(buildTime())
        
        let line = UIView()
        line.backgroundColor = .fill_2
        contentView.addSubview(line)
        line.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(16)
            make.top.equalTo(stackView.snp.bottom).offset(16)
            make.bottom.equalToSuperview().offset(-6).priority(.medium)
            make.height.equalTo(1)
        }
    }
    
    private func buildAlbum() -> UIView {
        let scrollView = UIScrollView()
        scrollView.isPagingEnabled = true
        scrollView.showsVerticalScrollIndicator = false
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.isHidden = true
        scrollView.delegate = self
        scrollView.backgroundColor = .primary_1
        
        stackView.distribution = .fillEqually
        scrollView.addSubview(stackView)
        stackView.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview()
            make.verticalEdges.equalToSuperview()
            make.height.equalToSuperview()
        }
        
        return scrollView
    }
    
    private func buildPage() -> UIView {
        let container = UIView()
        container.isHidden = true
        
        pageControl.pageIndicatorTintColor = .text_2
        pageControl.currentPageIndicatorTintColor = .text_4
        pageControl.preferredIndicatorImage = UIImage.image(for: .text_2, size: 4, cornerRadius: 2)
        pageControl.hidesForSinglePage = true
        container.addSubview(pageControl)
        pageControl.snp.makeConstraints { make in
            make.centerX.equalToSuperview()
            make.verticalEdges.equalToSuperview().inset(2)
            make.height.equalTo(4)
        }
        
        return container
    }
    
    private func buildContent() -> UIView {
        let container = UIView()
        
        contentLabel.font = .body_m
        contentLabel.textColor = .text_5
        contentLabel.text = " "
        contentLabel.numberOfLines = 0
        container.addSubview(contentLabel)
        contentLabel.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(16)
            make.verticalEdges.equalToSuperview()
        }
        
        return container
    }
    
    private func buildTime() -> UIView {
        let container = UIView()
        
        timeLabel.font = .body_xs
        timeLabel.textColor = .text_4
        timeLabel.text = " "
        container.addSubview(timeLabel)
        timeLabel.snp.makeConstraints { make in
            make.horizontalEdges.equalToSuperview().inset(16)
            make.verticalEdges.equalToSuperview()
        }
        
        return container
    }
    
    private func buildImageView() -> UIImageView {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        
        return imageView
    }
}
