//
//  BCAFuncallHandler.m
//  ChatAgentApp
//
//  Created by caoshiqian on 2025/4/18.
//

#import "BCAFuncallHandler.h"

static NSString *const BCAFuncallContentNameKey     = @"function_name";
static NSString *const BCAFuncallContentParamsKey   = @"parameter_list";

@implementation BCAFuncallItem
@end

@interface BCAFuncallHandler ()<BCAFuncallHandlerDelegate>

@property (nonatomic, strong) NSMutableDictionary<NSString *, Class> *handlerTypeDict;
@property (nonatomic, strong) NSMutableDictionary<NSString *, id<BCAFuncallHandler>> *handlerDict;

@end

@implementation BCAFuncallHandler

- (instancetype)init {
    self = [super init];
    if (self) {
        _handlerDict = [NSMutableDictionary dictionary];
        _handlerTypeDict = [NSMutableDictionary dictionary];
        [self registerDefaultHandlers];
    }
    return self;
}

- (void)registerDefaultHandlers {
    // 读取 funcall 列表
    NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"funcalltype" ofType:@"plist"];
    NSArray *funcallTypes = [NSArray arrayWithContentsOfFile:plistPath];
    
    if (!funcallTypes || funcallTypes.count == 0) {
        NSLog(@"[Funcall] Failed to load funcall types from funcalltype.plist");
        return;
    }
    
    for (NSDictionary *typeDict in funcallTypes) {
        NSString *typeName = typeDict[@"name"];
        BOOL enabled = [typeDict[@"enabled"] boolValue];
        
        if (!typeName || !enabled) {
            continue;
        }
        
        // 按照命名规则转换类名
        NSString *className = [self convertTypeNameToClassName:typeName];
        
        // 创建对应 handler 实例
        Class handlerClass = NSClassFromString(className);
        if (handlerClass) {
            [self registerHandlerClass:handlerClass forType:typeName];
            NSLog(@"[Funcall] load handler for type: %@, class: %@", typeName, className);
        } else {
            NSLog(@"[Funcall] Failed to create handler for type: %@, class: %@ not found", typeName, className);
        }
    }
}

/// adjust_volume -> BCAAdjustVolumeHandler
- (NSString *)convertTypeNameToClassName:(NSString *)typeName {
    NSArray *components = [typeName componentsSeparatedByString:@"_"];
    NSMutableString *className = [NSMutableString string];
    
    for (NSString *component in components) {
        if (component.length > 0) {
            [className appendString:[[component substringToIndex:1] uppercaseString]];
            if (component.length > 1) {
                [className appendString:[component substringFromIndex:1]];
            }
        }
    }
    
    return [NSString stringWithFormat:@"BCA%@Handler", className];
}

- (BOOL)registerHandlerClass:(Class)cls forType:(NSString *)type {
    if (type.length == 0 || ![cls conformsToProtocol:@protocol(BCAFuncallHandler)]) {
        return NO;
    }
    [self.handlerTypeDict setObject:cls forKey:type];
    return YES;
}

- (id<BCAFuncallHandler>)createHandlerForType:(NSString *)type {
    Class cls = [self.handlerTypeDict objectForKey:type];
    if (cls) {
        id<BCAFuncallHandler> handler = [[cls alloc] init];
        return handler;
    }
    return nil;
}

/**
 {
     "session_id": "1744718758902",
     "content": {
         "function_name": "adjust_volume",
         "parameter_list": [
             { "mode": "up" },
             { "value": "10" }
         ]
     }
 }
 */
- (BCAFuncallResult)executeFuncallWithSessionId:(NSString *)sessionId params:(NSString *)params {

    NSDictionary *callDict = [self dictWithJsonString:params];
    if (!callDict) {
        [self callbackError:@"内容为空" sessionId:sessionId];
        return BCAFuncallResultFail;
    }
    
    // 解析函数调用内容
    NSString *contentString = [callDict objectForKey:@"content"];
    NSDictionary *contentDict = [self dictWithJsonString:contentString];
    if (!contentDict) {
        [self callbackError:@"函数调用内容解析失败" sessionId:sessionId];
        return BCAFuncallResultFail;
    }
    
    NSString *functionName = [contentDict objectForKey:BCAFuncallContentNameKey];
    if (functionName.length == 0) {
        [self callbackError:@"函数名称为空" sessionId:sessionId];
        return BCAFuncallResultFail;
    }
    
    // 获取对应的处理器
    id<BCAFuncallHandler> handler = [self createHandlerForType:functionName];
    if (!handler) {
        [self callbackError:[NSString stringWithFormat:@"未找到处理器: %@", functionName] sessionId:sessionId];
        return BCAFuncallResultFail;
    }
    
    // 解析执行参数
    NSArray *funcallParams = [contentDict objectForKey:BCAFuncallContentParamsKey];
    NSMutableDictionary *paramsDict = [NSMutableDictionary dictionary];
    if ([funcallParams isKindOfClass:[NSDictionary class]]) {
        [paramsDict addEntriesFromDictionary:(NSDictionary *)funcallParams];
    } else {
        for (NSDictionary *param in funcallParams) {
            if ([param isKindOfClass:[NSDictionary class]] && param.allKeys.count > 0) {
                NSString *key = [param.allKeys firstObject];
                id val = [param objectForKey:key];
                [paramsDict setObject:val forKey:key];
            }
        }
    }
    
    BCAFuncallItem *item = [[BCAFuncallItem alloc] init];
    item.sessionId = sessionId;
    item.functionName = functionName;
    item.functionParams = paramsDict;
    
    NSLog(@"[Funcall] 执行 funcall: %@，参数: %@", functionName, [self jsonStrWithDict:paramsDict]);
    handler.delegate = self;
    [self.handlerDict setObject:handler forKey:sessionId];
    
    return [handler executeFuncallWithItem:item];
}

- (void)onAgentAudioStateChange:(int)state {
    for (id<BCAFuncallHandler> handler in self.handlerDict.allValues) {
        [handler onAgentAudioStateChange:state];
    }
}

- (void)callbackError:(NSString *)error sessionId:(NSString *)sessionId {
    NSError *err = [NSError errorWithDomain:NSCocoaErrorDomain code:-1000 userInfo:@{ NSLocalizedDescriptionKey: error }];
    [self funcallHandler:nil executeFinished:sessionId message:nil error:err];
}

#pragma mark - BCAFuncallHandlerDelegate

- (void)funcallHandler:(id<BCAFuncallHandler>)handler executeFinished:(NSString *)sessionId
               message:(NSString *)message error:(NSError *)error {
    
    // 清理 handler 缓存
    if ([handler shouldExitFuncallHandler]) {
        [self.handlerDict removeObjectForKey:sessionId];
    }
    [self.delegate funcallHandler:handler executeFinished:sessionId message:message error:error];
}

- (void)funcallHandler:(id<BCAFuncallHandler>)handler sendTextToTTS:(NSString *)text {
    [self.delegate funcallHandler:handler sendTextToTTS:text];
}

- (UIViewController *)funcallHandlerChatViewController:(id<BCAFuncallHandler>)handler {
    return [self.delegate funcallHandlerChatViewController:handler];
}

#pragma mark - util

- (NSDictionary *)dictWithJsonString:(NSString *)jsonString {
    if (jsonString.length == 0) {
        return nil;
    }
    NSData *data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error = nil;
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
    if (error) {
        return nil;
    }
    return dict;
}

- (NSString *)jsonStrWithDict:(NSDictionary *)dict {
    NSData *data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return str;
}

@end

@implementation BCAFuncallResultView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setupViews];
    }
    return self;
}

- (void)setupViews {
    self.backgroundColor = [UIColor whiteColor];
    self.layer.cornerRadius = 12.0;
    self.layer.shadowColor = [UIColor blackColor].CGColor;
    self.layer.shadowOffset = CGSizeMake(0, 2);
    self.layer.shadowOpacity = 0.1;
    self.layer.shadowRadius = 4.0;
}

- (CGSize)boundingRectWithSize:(CGSize)size {
    return size;
}

@end
