//
//  BCAMapPoiSearchHandler.m
//  ChatAgentApp
//
//  Created by caoshiqian on 2025/4/20.
//

#import "BCAMapPoiSearchHandler.h"
#import "BCAMapPoiSearchModel.h"
#import "BCALocationManager.h"
#import "BCAPoiSearchTask.h"
#import "BCAMapPoiSearchCardView.h"
#import "BCAMapPoiSearchViewController.h"
#import "BNaviUtil.h"

#import <BaiduMapAPI_Base/BMKBaseComponent.h>
#import <BaiduMapAPI_Search/BMKSearchComponent.h>
#import <BaiduMapAPI_Utils/BMKUtilsComponent.h>

static NSString *const kCurrentPositionTitle = @"我的位置";

@interface BCAMapPoiSearchHandler ()<BCALocationManagerDelegate, BMKPoiSearchDelegate>

@property (nonatomic, strong) BCAFuncallItem *funcallItem;
@property (nonatomic, strong) BCAMapPoiSearchModel *model;

@property (nonatomic, strong) BCALocationManager *locationManager;
@property (nonatomic, strong) BCALocation *currentPosition;
@property (nonatomic, strong) BCALocation *centerPosition;

@property (nonatomic, strong) BCAPoiSearchTask *searchTask;
@property (nonatomic, strong) BMKPoiSearch *poiSearch;
@property (nonatomic, strong) BMKPOISearchResult *poiSearchResult;
@property (nonatomic, strong) BCAMapPoiSearchCardView *cardView;

@property (nonatomic, assign) NSInteger funcallRetCode;

@end

@implementation BCAMapPoiSearchHandler

@synthesize delegate;

#pragma mark - BCAFuncallHandler

- (BCAFuncallItem *)funcallItem {
    return _funcallItem;
}

/**
 检索流程：
 1. 检查数据是否有效
 2. 地图SDK授权
 3. 如果类型是区域
    3.1 PoiSearch 城市内检索
 4. 如果类型是周边
    4.1 等待当前位置坐标信息回调
    4.2 如果有中心位置，PoiSearch 城市内检索中心位置坐标
    4.3 PoiSearch 周边检索
 */
- (BCAFuncallResult)executeFuncallWithItem:(nonnull BCAFuncallItem *)item {
    if (self.funcallItem) {
        [self callbackResult:item.sessionId code:BCAFuncallResultFail error:@"正在搜索中哦！"];
        return BCAFuncallResultSuccess;
    }
    
    self.funcallItem = item;
    self.model = [BCAMapPoiSearchModel modelWithParams:item.functionParams];
    
    if (self.model.keyword.length == 0) {
        [self callbackResult:item.sessionId code:BCAFuncallResultFail error:@"你想搜索什么呢？"];
        return BCAFuncallResultSuccess;
    }
    
    if (self.model.searchType == BCAMapPoiSearchTypeArea && self.model.center.length == 0) {
        [self callbackResult:item.sessionId code:BCAFuncallResultFail error:@"你想搜索哪里呢？"];
        return BCAFuncallResultSuccess;
    }
    
    // 初始化地图SDK，等待授权结束再执行操作
    [self initMapSDK];
    
    return BCAFuncallResultSuccess;
}

- (BOOL)shouldExitFuncallHandler {
    if (self.funcallRetCode != BCAFuncallResultSuccess) {
        return YES;
    }
    return nil == [self funcallResultView];
}

- (BCAFuncallResultView *)funcallResultView {
    return self.cardView;
}

- (void)onAgentAudioStateChange:(int)state {
    // noop
}

- (void)dealloc {
    [[BNaviUtil sharedInstance] removeObserver:self forKeyPath:@"mapInitState"];
}

#pragma mark - MapSDK

- (void)initMapSDK {
    [[BNaviUtil sharedInstance] addObserver:self forKeyPath:@"mapInitState"
                                    options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:nil];
    [[BNaviUtil sharedInstance] initMap];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey, id> *)change
                       context:(void *)context {
    
    if ([keyPath isEqualToString:@"mapInitState"]) {
        BNaviInitState state = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        NSLog(@"[map] sdk mapInitState: %@", @(state));
        if (state == BNaviInitStateInited) {
            // 地图初始化成功
            [self startPoiSearch];
        }
    }
}

#pragma mark - PoiSearch

- (void)startPoiSearch {
    if (self.model.searchType == BCAMapPoiSearchTypeArea) {
        // 区域检索，不依赖位置信息
        [self searchPoi];
    } else {
        // 周边检索需要等待定位结果
        [self startLocating];
    }
}

- (void)searchPoi {
    self.poiSearch = [[BMKPoiSearch alloc] init];
    self.poiSearch.delegate = self;
    
    BOOL ret = YES;
    if (self.centerPosition) {
        // 周边
        NSLog(@"[poi] search nearby keyword: %@, coord: (%.2f, %.2f)", self.model.keyword,
              self.centerPosition.coordinate.latitude, self.centerPosition.coordinate.longitude);
        BMKPOINearbySearchOption *nearbyOption = [[BMKPOINearbySearchOption alloc] init];
        nearbyOption.keywords = @[self.model.keyword];
        nearbyOption.location = self.centerPosition.coordinate;
        nearbyOption.radius = self.model.radius;
        nearbyOption.isRadiusLimit = NO;
        nearbyOption.scope = BMK_POI_SCOPE_DETAIL_INFORMATION;
//        nearbyOption.pageIndex = 0;
//        nearbyOption.pageSize = 10;
        ret = [self.poiSearch poiSearchNearBy:nearbyOption];
    } else {
        // 区域
        NSLog(@"[poi] search area keyword: %@ in area: %@", self.model.keyword, self.model.center);
        BMKPOICitySearchOption *cityOption = [[BMKPOICitySearchOption alloc] init];
        cityOption.keyword = self.model.keyword;
        cityOption.city = self.model.center;
        cityOption.isCityLimit = YES;
        // POI检索结果详细程度
        cityOption.scope = BMK_POI_SCOPE_DETAIL_INFORMATION; // or BMK_POI_SCOPE_BASIC_INFORMATION
        // 检索过滤条件，scope字段为BMK_POI_SCOPE_DETAIL_INFORMATION时，filter字段才有效
//        cityOption.filter = filter;
//        cityOption.pageIndex = 0;
//        cityOption.pageSize = 10;
        ret = [self.poiSearch poiSearchInCity:cityOption];
    }
    
    if (!ret) {
        [self callbackResult:self.funcallItem.sessionId code:BCAFuncallResultFail error:@"查询失败"];
    }
}

- (void)searchCenter {
    if (self.model.center.length > 0) {
        // 基于指定位置，需要在当前城市查询坐标
        BCALocation *center = [BCALocation new];
        center.name = self.model.center;
        
        __weak typeof(self) weakSelf = self;
        self.searchTask = [[BCAPoiSearchTask alloc] initWithLocations:@[center] currentLocation:self.currentPosition
                                                           completion:^(NSArray<BCALocation *> * _Nullable results, NSError * _Nullable error) {
            
            __strong typeof(self) strongSelf = weakSelf;
            if (error) {
                NSLog(@"[poi] search center err: %@", @(strongSelf.searchTask.searchErrorCode));
                [strongSelf callbackResult:self.funcallItem.sessionId
                                      code:BCAFuncallResultFail
                                     error:@"没有找到中心位置"];
                return;
            }
            strongSelf.centerPosition = [results firstObject];
            [strongSelf searchPoi];
        }];
        [self.searchTask start];
    } else {
        // 基于当前位置，直接检索
        self.centerPosition = self.currentPosition;
        [self searchPoi];
    }
}

#pragma mark - BMKPoiSearchDelegate

- (void)onGetPoiResult:(BMKPoiSearch *)searcher result:(BMKPOISearchResult *)poiResult errorCode:(BMKSearchErrorCode)errorCode {
    // 按需添加翻页查询逻辑
    if (errorCode != BMK_SEARCH_NO_ERROR || poiResult.poiInfoList.count == 0) {
        NSLog(@"[poi] search error：%@, list count: %@", @(errorCode), @(poiResult.poiInfoList.count));
        [self callbackResult:self.funcallItem.sessionId code:BCAFuncallResultFail error:@"查询失败"];
        return;
    }
    
    self.poiSearchResult = poiResult;
    [self.cardView updateWithSearchResult:poiResult];
    [self callbackResult:self.funcallItem.sessionId error:nil];
    NSLog(@"[poi] search result：%@", poiResult.poiInfoList);
}

#pragma mark - LocationManager

- (BCALocationManager *)locationManager {
    if (!_locationManager) {
        _locationManager = [[BCALocationManager alloc] init];
        _locationManager.delegate = self;
    }
    return _locationManager;
}

- (void)startLocating {
    [self.locationManager requestLocationPermission];
    [self.locationManager stopUpdatingLocation];
    [self.locationManager startUpdatingLocation];
}

- (void)stopLocating {
    [self.locationManager stopUpdatingLocation];
}

- (void)locationManagerDidChangeAuthorizationStatus:(BOOL)authorized {
    CLAuthorizationStatus status = [self.locationManager authorizationStatus];
    NSLog(@"[map][location] didChangeAuthorizationStatus: %@, authorized: %@", @(status), @(authorized));
}

- (void)locationManagerDidUpdateLocation:(BCALocation *)location {
    NSLog(@"[map][location] didUpdateLocation: %@", location.description);
    location.coordinate = BMKCoordTrans(location.coordinate, BMK_COORDTYPE_GPS, BMK_COORDTYPE_BD09LL);
    [self stopLocating];
    
    self.currentPosition = location;
    self.currentPosition.name = kCurrentPositionTitle;
    [self searchCenter];
}

- (void)locationManagerDidFailWithError:(NSError *)error {
    NSLog(@"[map][location] didFailWithError: %@", error);
    [self callbackResult:self.funcallItem.sessionId code:BCAFuncallResultFail error:@"请打开定位权限"];
}

#pragma mark - CardView & MapPage

- (BCAMapPoiSearchCardView *)cardView {
    if (!_cardView) {
        _cardView = [[BCAMapPoiSearchCardView alloc] initWithFrame:CGRectZero];
        
        // 简易交互
        UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapCardView:)];
        [_cardView addGestureRecognizer:tapGR];
    }
    return _cardView;
}

- (void)tapCardView:(UITapGestureRecognizer *)gr {
    [self enterMapPage];
}

- (void)enterMapPage {
    BCAMapPoiSearchViewController *vc = [[BCAMapPoiSearchViewController alloc] init];
    vc.poiResult = self.poiSearchResult;
    [self naviToVC:vc];
}

- (UIViewController *)chatViewController {
    UIViewController *vc = [self.delegate funcallHandlerChatViewController:self];
    if (vc.navigationController) {
        return vc.navigationController;
    }
    return vc;
}

- (void)naviToVC:(UIViewController *)vc {
    UIViewController *baseVC = [self chatViewController];
    if ([baseVC isKindOfClass:[UINavigationController class]]) {
        [((UINavigationController *)baseVC) pushViewController:vc animated:YES];
    } else {
        vc.modalPresentationStyle = UIModalPresentationFullScreen;
        [baseVC presentViewController:vc animated:YES completion:^{
                    
        }];
    }
}

#pragma mark - Callback

- (void)callbackResult:(NSString *)sessionId code:(NSInteger)code error:(NSString *)errorStr {
    self.funcallRetCode = code;
    if (self.delegate) {
        NSError *error = code == BCAFuncallResultFail ? [NSError errorWithDomain:NSCocoaErrorDomain code:code userInfo:@{ NSLocalizedDescriptionKey: errorStr }] : nil;
        NSString *message = code == BCAFuncallResultFail ? nil : @"找到以下结果，点击查看详情";
        [self.delegate funcallHandler:self executeFinished:sessionId message:message error:error];
    }
}

- (void)callbackResult:(NSString *)sessionId error:(NSError *)error {
    self.funcallRetCode = BCAFuncallResultSuccess;
    if (self.delegate) {
        [self.delegate funcallHandler:self executeFinished:sessionId message:nil error:error];
    }
}

@end
