//
//  SearchViewModel.swift
//  SodaLive
//
//  Created by klaus on 3/27/25.
//

import Foundation
import Combine

final class SearchViewModel: ObservableObject {
    enum CurrentTab: String {
        case UNIFIED, CREATOR, CONTENT, SERIES
    }
    
    private let repository = SearchRepository()
    private var subscription = Set<AnyCancellable>()
    
    @Published var currentTab: CurrentTab = .UNIFIED {
        didSet {
            if currentTab == .CREATOR && searchCreatorItemList.isEmpty {
                self.searchCreatorList()
            } else if currentTab == .CONTENT && searchContentItemList.isEmpty {
                self.searchContentList()
            } else if currentTab == .SERIES && searchSeriesItemList.isEmpty {
                self.searchSeriesList()
            }
        }
    }
    
    @Published var errorMessage = ""
    @Published var isShowPopup = false
    @Published var isLoading = false
    
    @Published var keyword = ""
    
    @Published var searchUnifiedCreatorList: [SearchResponseItem] = []
    @Published var searchUnifiedContentList: [SearchResponseItem] = []
    @Published var searchUnifiedSeriesList: [SearchResponseItem] = []
    
    @Published var searchCreatorItemList: [SearchResponseItem] = []
    @Published var searchContentItemList: [SearchResponseItem] = []
    @Published var searchSeriesItemList: [SearchResponseItem] = []
    
    var searchCreatorPage = 1
    var searchContentPage = 1
    var searchSeriesPage = 1
    
    var isSearchCreatorLast = false
    var isSearchContentLast = false
    var isSearchSeriesLast = false
    
    private var pageSize = 20
    
    init() {
        _keyword = Published(initialValue: "")
        $keyword
            .debounce(for: .seconds(0.3), scheduler: RunLoop.main)
            .sink { [unowned self] value in
                UserDefaults.set(value, forKey: .searchChannel)
                if value.count > 1 {
                    self.searchUnified()
                } else {
                    self.initList()
                }
            }
            .store(in: &subscription)
    }
    
    func initList() {
        searchCreatorPage = 1
        searchContentPage = 1
        searchSeriesPage = 1
        
        isSearchCreatorLast = false
        isSearchContentLast = false
        isSearchSeriesLast = false
        
        searchUnifiedCreatorList.removeAll()
        searchUnifiedContentList.removeAll()
        searchUnifiedSeriesList.removeAll()
        
        searchCreatorItemList.removeAll()
        searchContentItemList.removeAll()
        searchSeriesItemList.removeAll()
    }
    
    func searchUnified() {
        if !isLoading {
            if currentTab != .UNIFIED {
                currentTab = .UNIFIED
            }
            
            initList()
            
            isLoading = true
            
            repository.searchUnified(keyword: keyword)
                .sink { result in
                    switch result {
                    case .finished:
                        DEBUG_LOG("finish")
                    case .failure(let error):
                        ERROR_LOG(error.localizedDescription)
                    }
                } receiveValue: { [unowned self] response in
                    self.isLoading = false
                    let responseData = response.data
                    
                    do {
                        let jsonDecoder = JSONDecoder()
                        let decoded = try jsonDecoder.decode(ApiResponse<SearchUnifiedResponse>.self, from: responseData)
                        
                        if let data = decoded.data, decoded.success {
                            DEBUG_LOG("test: \(data)")
                            searchUnifiedCreatorList.append(contentsOf: data.creatorList)
                            searchUnifiedContentList.append(contentsOf: data.contentList)
                            searchUnifiedSeriesList.append(contentsOf: data.seriesList)
                        } else {
                            if let message = decoded.message {
                                self.errorMessage = message
                            } else {
                                self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                            }
                            
                            self.isShowPopup = true
                        }
                    } catch {
                        DEBUG_LOG("error: \(error)")
                        self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                        self.isShowPopup = true
                    }
                }
                .store(in: &subscription)
        }
    }
    
    func searchCreatorList() {
        if !isLoading && !isSearchCreatorLast {
            isLoading = true
            
            repository.searchCreatorList(keyword: keyword, page: searchCreatorPage, size: pageSize)
                .sink { result in
                    switch result {
                    case .finished:
                        DEBUG_LOG("finish")
                    case .failure(let error):
                        ERROR_LOG(error.localizedDescription)
                    }
                } receiveValue: { [unowned self] response in
                    self.isLoading = false
                    let responseData = response.data
                    
                    do {
                        let jsonDecoder = JSONDecoder()
                        let decoded = try jsonDecoder.decode(ApiResponse<SearchResponse>.self, from: responseData)
                        
                        if let data = decoded.data, decoded.success {
                            DEBUG_LOG("test: \(data)")
                            self.searchCreatorPage += 1
                            self.searchCreatorItemList.append(contentsOf: data.items)
                            
                            if data.items.isEmpty {
                                self.isSearchCreatorLast = true
                            }
                        } else {
                            if let message = decoded.message {
                                self.errorMessage = message
                            } else {
                                self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                            }
                            
                            self.isShowPopup = true
                        }
                    } catch {
                        ERROR_LOG("test: \(error)")
                        self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                        self.isShowPopup = true
                    }
                }
                .store(in: &subscription)
        }
    }
    
    func searchContentList() {
        if !isLoading && !isSearchContentLast {
            isLoading = true
            
            repository.searchContentList(keyword: keyword, page: searchContentPage, size: pageSize)
                .sink { result in
                    switch result {
                    case .finished:
                        DEBUG_LOG("finish")
                    case .failure(let error):
                        ERROR_LOG(error.localizedDescription)
                    }
                } receiveValue: { [unowned self] response in
                    self.isLoading = false
                    let responseData = response.data
                    
                    do {
                        let jsonDecoder = JSONDecoder()
                        let decoded = try jsonDecoder.decode(ApiResponse<SearchResponse>.self, from: responseData)
                        
                        if let data = decoded.data, decoded.success {
                            DEBUG_LOG("test: \(data)")
                            self.searchContentPage += 1
                            self.searchContentItemList.append(contentsOf: data.items)
                            
                            if data.items.isEmpty {
                                self.isSearchContentLast = true
                            }
                        } else {
                            if let message = decoded.message {
                                self.errorMessage = message
                            } else {
                                self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                            }
                            
                            self.isShowPopup = true
                        }
                    } catch {
                        ERROR_LOG("test: \(error)")
                        self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                        self.isShowPopup = true
                    }
                }
                .store(in: &subscription)
        }
    }
    
    func searchSeriesList() {
        if !isLoading && !isSearchSeriesLast {
            isLoading = true
            
            repository.searchSeriesList(keyword: keyword, page: searchSeriesPage, size: pageSize)
                .sink { result in
                    switch result {
                    case .finished:
                        DEBUG_LOG("finish")
                    case .failure(let error):
                        ERROR_LOG(error.localizedDescription)
                    }
                } receiveValue: { [unowned self] response in
                    self.isLoading = false
                    let responseData = response.data
                    
                    do {
                        let jsonDecoder = JSONDecoder()
                        let decoded = try jsonDecoder.decode(ApiResponse<SearchResponse>.self, from: responseData)
                        
                        if let data = decoded.data, decoded.success {
                            DEBUG_LOG("test; \(data)")
                            self.searchSeriesPage += 1
                            self.searchSeriesItemList.append(contentsOf: data.items)
                            
                            if data.items.isEmpty {
                                self.isSearchSeriesLast = true
                            }
                        } else {
                            if let message = decoded.message {
                                self.errorMessage = message
                            } else {
                                self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                            }
                            
                            self.isShowPopup = true
                        }
                    } catch {
                        ERROR_LOG("test: \(error)")
                        self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다."
                        self.isShowPopup = true
                    }
                }
                .store(in: &subscription)
        }
    }
}
