#include "XUDPServer.h"
#import <Foundation/Foundation.h>
#import "IPhoneHertbeat.h"
#import "XSHackIos.h"
#import "XSHelper.h"
#import "XSPhoneInfo.h"
#import "XSPhoneConfig.h"
#import "MyAdServer.h"
#import "MyAdTask2.h"
#import "MyEventBus.h"

BOOL myadTaskManualStop = NO;

@interface MyAdTask2Mangger()
{
@private
    BOOL running;
    dispatch_source_t _timer;
    NSDate *lastRun;
    NSDate *lastGetCountry;
    NSString *_lastIdfa;
    NSString *taskId;
    NSString *taskAppId;
    int workType;
    int screen_w;
    int screen_h;
    int adAfter;
    NSString *linkId;
    NSString *dataId;
    NSString *remoteIp;
    NSString *country;

}

@property (nonatomic, assign) NSTimeInterval lastAppSwitchTime; // 新增属性

@end

@implementation MyAdTask2Mangger

+(instancetype)sharedInstance {
    static MyAdTask2Mangger* _sharedInstance = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedInstance = [[MyAdTask2Mangger alloc] init];
    });
    return _sharedInstance;
}

-(instancetype)init {
    if (self = [super init]) {
        self->running = NO;
        self->_lastIdfa = @"";
        self.manQueue = dispatch_queue_create("com.xyzshell.myadtask", DISPATCH_QUEUE_SERIAL);
        CGFloat screen_scale = [[UIScreen mainScreen] scale];
        CGFloat device_screen_width = [UIScreen mainScreen].bounds.size.width * screen_scale;
        CGFloat device_screen_height = [UIScreen mainScreen].bounds.size.height * screen_scale;
        self->screen_w = device_screen_width;
        self->screen_h = device_screen_height;
        self->adAfter = 1000;
        self.lastAppSwitchTime = 0; // 初始化为0
        return self;
    }
    return nil;
}

- (int)onShow:(NSDictionary *)dic {
    if(dic == nil || [dic isEqual:[NSNull null]] || [dic count] <= 0) {
        return 4000;
    }
    NSString *t_appid = [self getStr:@"appid" dic:dic];
    NSString *t_idfa = [self getStr:@"idfa" dic:dic];
    NSString *t_adId = [self getStr:@"id" dic:dic];
    NSNumber *t_ecpm = [self getNum:@"ecpm" dic:dic];
    BOOL ad = dic[@"ad"];
    NSString *iphoneId = [[XSPhoneConfig sharedInstance] IPhoneName];
    
    if(!ad) {
        NSLog(@"XS- no ad show");
        return 0;
    }
    int close = 4000;
    
    AdLoadInfo adloadInfo = getAdLoadInfo(@{
        @"idfa": t_idfa ?: @"",
        @"adId": t_adId ?: @"",
        @"ecpm": [NSString stringWithFormat:@"%@", t_ecpm],
        @"appId": t_appid ?: @"",
        @"deviceId":iphoneId ?: @""
    });
    
    close = [adloadInfo.adTime intValue];
    int before = [adloadInfo.adTouchBeforeMs intValue];
    if (before >= close) {
        before = 1000;
    }
    int after = [adloadInfo.adTouchAfterMs intValue];
    if(after > 1000) {
        self->adAfter = after;
    } else {
        self->adAfter = 1000;
    }
    
    NSInteger random1 = arc4random_uniform(101);
    NSInteger tr = [adloadInfo.touchRate intValue];
    if (tr > random1) {
        double beforeSec = before / 1000.0;
        __weak typeof(self) weakSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(beforeSec * NSEC_PER_SEC)), 
                       self.manQueue, ^{
            [weakSelf touchAppTask:0];
        });
    }
    return close;
}

- (void)showStatus:(NSString *)data {
    [[MyEventBus sharedInstance] postEvent:@"UpdateStatus" withObject:data];
}

- (void)setRemoteInfo {
    NSString *url = @"https://ipapi.co/json/";
    XSHttpHelper *http = [[XSHttpHelper alloc] init];
    __weak typeof(self) weakSelf = self;
    [http doGET:url withCallback:^(NSData *data) {
        if(!data) {
            NSLog(@"!setRemoteInfo 1data");
            [weakSelf showStatus:@"!setRemoteInfo 1data"];
            return;
        }
        NSDictionary *dic = [XSHelper jsonData2Dictionary:data];
        if (!dic) {
            NSLog(@"!setRemoteInfo dic");
            [weakSelf showStatus:@"!setRemoteInfo dic"];
            return;
        }
        NSString *isoCode = dic[@"country_code"];
        NSString *ip = dic[@"ip"];
        
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return;
        
        strongSelf->remoteIp = [ip copy];
        strongSelf->country = [isoCode copy];
        [XSPhoneInfo sharedInstance].remoteIp = [NSString stringWithFormat:@"%@:%@", isoCode, ip];
        [weakSelf showStatus:[XSPhoneInfo sharedInstance].remoteIp];
    } withError:^(NSError *err) {
        NSLog(@"!setRemoteInfo err:%@",err);
        [weakSelf showStatus:[NSString stringWithFormat:@"%@", err.description]];
    }];
}

- (void)setRemoteInfo1 {
    NSString *url = [[XSPhoneConfig sharedInstance] GetRemoteIPURL];
    [self showStatus:url];
    if (!url) {
        NSLog(@"!setRemoteInfo url");
        return;
    }
    __weak typeof(self) weakSelf = self;
    
    XSHttpHelper *http = [[XSHttpHelper alloc] init];
    [http doGET:url withCallback:^(NSData *data) {
        if(!data) {
            NSLog(@"!setRemoteInfo 1data");
            [weakSelf showStatus:@"!setRemoteInfo 1data"];
            return;
        }
        NSDictionary *dic = [XSHelper jsonData2Dictionary:data];
        if (!dic) {
            NSLog(@"!setRemoteInfo dic");
            [weakSelf showStatus:@"!setRemoteInfo dic"];
            return;
        }
        NSDictionary *_data = dic[@"data"];
        if(!_data) {
            NSLog(@"!setRemoteInfo data");
            [weakSelf showStatus:@"!setRemoteInfo data"];
            return;
        }
        NSString *isoCode = _data[@"isoCode"];
        NSString *ip = _data[@"ip"];
        NSLog(@"setRemoteInfo:%@", _data);
        
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return;
        
        strongSelf->remoteIp = [ip copy];
        strongSelf->country = [isoCode copy];
        [XSPhoneInfo sharedInstance].remoteIp = [NSString stringWithFormat:@"%@:%@", isoCode, ip];
        [weakSelf showStatus:[XSPhoneInfo sharedInstance].remoteIp];
    } withError:^(NSError *err) {
        NSLog(@"!setRemoteInfo err:%@",err);
        [weakSelf showStatus:[NSString stringWithFormat:@"%@", err.description]];
    }];
}

- (BOOL)onEnd:(NSDictionary *)dic {
    NSNumber *maxEcpm = dic[@"max_ecpm"];
    int sec = self->adAfter / 1000;
    __weak typeof(self) weakSelf = self;
    if([maxEcpm doubleValue] <= 0.0) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, sec * NSEC_PER_SEC), self.manQueue, ^{
            @autoreleasepool {
                [weakSelf startApp];
            }
        });
        return NO;
    }
    BOOL res = needAdContinue(self->taskAppId, self->_lastIdfa, maxEcpm);
    if(res) {
        return YES;
    }
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, sec * NSEC_PER_SEC), self.manQueue, ^{
        @autoreleasepool {
            [weakSelf startApp];
        }
    });
    return NO;
}

- (void)startApp {
    @autoreleasepool {
        if(!self->running){
            return;
        }
        self->lastRun = [NSDate date];
        if (self->country == nil || [self->country isEqual:NULL] || [self->country isEqual:@""]) {
            [self setRemoteInfo];
            self->lastGetCountry = [NSDate date];
        } else {
            NSDate *curRunTime = [NSDate date];
            NSTimeInterval elapsed = [curRunTime timeIntervalSinceDate:self->lastGetCountry];
            if (elapsed >= 300) {
                [self setRemoteInfo];
                self->lastGetCountry = [NSDate date];
            }
        }
        
        __weak typeof(self) weakSelf = self;
        getChangeInfo(self->_lastIdfa, ^(NSDictionary *dic) {
            dispatch_async(weakSelf.manQueue, ^{
                [weakSelf onChangeInfo:dic];
            });
        }, ^(NSError *err) {
            NSLog(@"XS- startTask NSError is null, %@", err);
        });
    }
}

- (void)start {
    self->running = YES;
    myadTaskManualStop = NO;
    [[IPhoneHertbeat sharedInstance] setStatus:@"运行中"];
    [self startApp];
    __weak typeof(self) weakSelf = self;
    // 确保Timer在重新启动前被取消
    if (_timer) {
        dispatch_source_cancel(_timer);
        _timer = nil;
    }
    // 使用 dispatch_source 创建timer
    _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, self.manQueue);
    dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), 10 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(_timer, ^{
        @autoreleasepool {
            [weakSelf proc];
        }
    });
    dispatch_resume(_timer);
    [[MyEventBus sharedInstance] postEvent:@"UpdateRunStatus" withObject:@(YES)];
}

- (void)proc {
    if (!self->running) {
        return;
    }
    
    NSLog(@"XS- MyAdTaskManager proc");
    NSDate* curRunTime = [NSDate date];
    NSTimeInterval elapsed = [curRunTime timeIntervalSinceDate:self->lastRun];
    
    if (elapsed >= 30) {
        //[self onStop];
        [self start];
        
    } else {
        NSString* appId = [ self frontMostAppId];
        
        if (![appId isEqual: self->taskAppId]) {
            // 引入冷却时间，避免频繁切换应用
            NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
            if (currentTime - self.lastAppSwitchTime < 30) { // 30秒冷却时间
                NSLog(@"XS- App switching throttled. Last switch was %.0f seconds ago.", currentTime - self.lastAppSwitchTime);
                return;
            }

            [self appKill:appId];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), self.manQueue, ^{
                [self appRun:self->taskAppId];
                self.lastAppSwitchTime = [NSDate timeIntervalSinceReferenceDate]; // 更新切换时间
            });
        }
    }
}

- (NSString *)toggle {
    if(self->running) {
        [self stop];
    } else {
        [self start];
    }
    return [IPhoneHertbeat sharedInstance].status;
}

- (void)stop {
    myadTaskManualStop = YES;
    self->running = NO;
    [IPhoneHertbeat sharedInstance].status = @"已停止";
    if (_timer) {
        dispatch_source_cancel(_timer);
        _timer = nil;
    }
    [[MyEventBus sharedInstance] postEvent:@"UpdateRunStatus" withObject:@(NO)];
}

- (NSString *)getSystemInfo {
    void *buffer = NULL;
    NSString *result = nil;
    
    // 设置 sysctl 的 mib 参数
    // 0x100000006LL 拆分为两个 int: {6, 1}
    // 高32位是1 (0x1), 低32位是6 (0x6)
    int mib[2];
    mib[0] = 6;  // CTL_HW
    mib[1] = 1;  // HW_MACHINE
    
    size_t size = 100;
    
    // 第一次调用获取实际需要的缓冲区大小
    // #import <sys/sysctl.h>
    sysctl(mib, 2, NULL, &size, NULL, 0);
    
    // 分配内存
    buffer = malloc(size);
    
    if (buffer != NULL) {
        // 第二次调用获取实际数据
        sysctl(mib, 2, buffer, &size, NULL, 0);
        
        // 转换为 NSString
        result = [NSString stringWithUTF8String:(const char *)buffer];
        
        // 释放内存
        free(buffer);
    }
    
    return result;
}

- (void)onChangeInfo:(NSDictionary *)dic {
    NSString* t_idfa = [self getStr:@"idfa" dic:dic];
    if (![XSHelper strIsEmpty:t_idfa]) {
        self->_lastIdfa = [t_idfa copy];
    } else {
        NSLog(@"XS- startTask t_idfa is null");
        return;
    }
    
    NSString *_linkId = [self getStr:@"linkId" dic:dic];
    if (![XSHelper strIsEmpty:_linkId]) {
        self->linkId = [_linkId copy];
    }
    NSString *_dataId = [self getStr:@"dataId" dic:dic];
    if (![XSHelper strIsEmpty:_dataId]) {
        self->dataId = [_dataId copy];
    }
    
    NSString* t_taskId = [self getStr:@"id" dic:dic];
    if (![XSHelper strIsEmpty:t_taskId]) {
        self->taskId = [t_taskId copy];
    } else {
        NSLog(@"XS- startTask t_taskId is null");
        return;
    }
    NSString* t_taskAppId = [self getStr:@"appId" dic:dic];
    if (![XSHelper strIsEmpty:t_taskAppId]) {
        self->taskAppId = [t_taskAppId copy];
        [IPhoneHertbeat sharedInstance].appId = self->taskAppId;
    } else {
        NSLog(@"XS- startTask t_taskAppId is null");
        return;
    }
    
    
    __weak typeof(self) weakSelf = self;
    [self restart:^{
        __strong typeof(weakSelf) strongSelf = weakSelf;
        if (!strongSelf) return;
        
        saveChangeDataFile(dic);
        strongSelf->running = YES;
        
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), 
                       strongSelf.manQueue, ^{
            __strong typeof(weakSelf) strongSelf2 = weakSelf;
            if (!strongSelf2) return;
            
            [strongSelf2 appRun:strongSelf2->taskAppId];
        });
    }];
}

- (void)appKill:(NSString*)app {
    NSLog(@"XS- appKill");
    XSKillAppByName(app);
}

- (void)unlock {
    NSLog(@"XS- unlock");
    dispatch_async(dispatch_get_main_queue(), ^{
        XSRemoteUnlock();
    });
}

- (void)resetApp:(NSString*)appId callback:(OnEndCallback)callback {
    NSLog(@"XS- JSApi resetApp");
    NSString *appInfoPath = XSGetAppInfoPath(appId);
    NSDictionary *appInfo = XSGetAppInfo(appInfoPath);
    id bfaceDictKey = appInfo[@"bfaceDictKey"];
    NSMutableDictionary *tempBfaceDictKey = nil;
    if(bfaceDictKey) {
        tempBfaceDictKey = [NSMutableDictionary dictionaryWithDictionary:bfaceDictKey];
    } else {
        tempBfaceDictKey = [[NSMutableDictionary alloc] init];
    }
    NSString *serverUrl = [[XSPhoneConfig sharedInstance] ServerURL];
    BOOL washParam = [[XSPhoneConfig sharedInstance] WashParam];
    [tempBfaceDictKey setValue:serverUrl forKey:@"adbrush_base_url"];
    [tempBfaceDictKey setValue:@(washParam) forKey:@"washParam"];
        // [tempBfaceDictKey setValue:lowEcpm forKey:@"adbrush_ecpm"];
    if(self->linkId) {
        [tempBfaceDictKey setValue:self->linkId forKey:@"linkId"];
    } else {
        NSString *linkId = [[NSUUID UUID] UUIDString];
        [tempBfaceDictKey setValue:linkId forKey:@"linkId"];
    }
    
    if(self->dataId) {
        [tempBfaceDictKey setValue:self->dataId forKey:@"dataId"];
    } else {
        [tempBfaceDictKey setValue:@"0" forKey:@"dataId"];
    }
    if(self->remoteIp) {
        [tempBfaceDictKey setValue:self->remoteIp forKey:@"remoteIp"];
    }
    uint16_t udp_port = [XUDPServer sharedInstance].udp_port;
    [tempBfaceDictKey setValue:@(udp_port) forKey:@"udp_port"];
    [tempBfaceDictKey setValue:[self getSystemInfo] forKey:@"device_model"];
    
    NSLog(@"XS- resetApp 1");
    NSMutableDictionary *tempAppInfo = [[NSMutableDictionary alloc] init];
    [tempAppInfo setValue:tempBfaceDictKey forKey:@"bfaceDictKey"];
    
    XSClearAll(appId);
    
    XSSaveAppInfo(tempAppInfo, appInfoPath);
    callback();
    
}

- (NSString *)frontMostAppId {
    return XSFrontMostAppId();
}

- (void)appRun:(NSString *)appId {
    if ([XSHelper strIsEmpty:appId]) return;
    
    dispatch_async(dispatch_get_main_queue(), ^{
        @try {
            bringAppToForeground(appId);
        } @catch (NSException *exception) {
            NSLog(@"Error bringing app to foreground: %@", exception);
        }
    });
}

- (void)tap:(int)i x:(int)x y:(int)y {
}

- (void)restart:(OnEndCallback)callback {
    __weak typeof(self) weakSelf = self;
    dispatch_async(self.manQueue, ^{
        @try {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            if (!strongSelf) return;
            
            [weakSelf appKill:@"com.apple.AppStore"];
            [weakSelf appKill:@"com.apple.mobilesafari"];
            if (strongSelf->taskAppId && ![strongSelf->taskAppId isEqual:[NSNull null]] && [strongSelf->taskAppId length] > 0) {
                [weakSelf appKill:strongSelf->taskAppId];
                [weakSelf unlock];
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), strongSelf.manQueue, ^{
                    [weakSelf unlock];
                    [weakSelf resetApp:strongSelf->taskAppId callback:callback];
                });
            }
        } @catch (NSException *exception) {
            NSLog(@"Error in restart: %@", exception);
        }
    });
}

- (void)rndTouchApp {
    int times = [XSHelper random:2 and:4];
    [self _rndTouchAppRecursive:0 totalTimes:times];
}

- (void)_rndTouchAppRecursive:(int)currentIndex totalTimes:(int)times {
    if (currentIndex >= times) {
        return;
    }
    
    int x = [XSHelper random:40 and:screen_w - 20];
    int y = [XSHelper random:50 and:screen_h - 240];
    NSString* appId = [self frontMostAppId];
    
    if ([appId isEqual:self->taskAppId]) {
        [self tap:1 x:x y:y];
        
        __weak typeof(self) weakSelf = self;
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.002 * NSEC_PER_SEC)), 
                       self.manQueue, ^{
            [weakSelf _rndTouchAppRecursive:currentIndex + 1 totalTimes:times];
        });
    }
}

- (void)touchAppTask:(int)beforeTouch {
    __weak typeof(self) weakSelf = self;
    
    if (beforeTouch > 0) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(beforeTouch * NSEC_PER_SEC)), self.manQueue, ^{
            [self rndTouchApp];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), self.manQueue, ^{
                int x = [XSHelper random:40 and:screen_w - 20];
                int y = [XSHelper random:50 and:screen_h - 240];
                [self tap:1 x:x y:y];
                
                NSString* appId = [ self frontMostAppId];
                if (![appId isEqual: self->taskAppId]) {
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), self.manQueue, ^{
                        [self appRun:self->taskAppId];
                    });
                } else {
                    [self appRun:self->taskAppId];
                }
            });
        });
    } else {
        [self rndTouchApp];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), self.manQueue, ^{
            int x = [XSHelper random:40 and:screen_w - 20];
            int y = [XSHelper random:50 and:screen_h - 240];
            [self tap:1 x:x y:y];
            
            NSString* appId = [ self frontMostAppId];
            if (![appId isEqual: self->taskAppId]) {
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), self.manQueue, ^{
                    [self appRun:self->taskAppId];
                });
            } else {
                [self appRun:self->taskAppId];
            }
        });
    }
}

- (NSString*)getStr:(NSString *)key dic:(NSDictionary*)dic {
    NSLog(@"getStr: %@", key);
    id t_idfa = dic[key];
    if (t_idfa && ![t_idfa isEqual:[NSNull null]] && ![t_idfa isEqual:@""]) {
        return [NSString stringWithFormat:@"%@", t_idfa];
    } else {
        NSLog(@"XS- dic %@ is null", key);
        return @"";
    }
}

- (NSNumber*)getNum:(NSString *)key dic:(NSDictionary*)dic {
    NSLog(@"getNum: %@", key);
    id t_idfa = dic[key];
    NSString *ecpm_str = [NSString stringWithFormat:@"%@", t_idfa];
    
    NSNumber *ecpm = @0.0;
    
    if (ecpm_str && ![ecpm_str isEqual:[NSNull null]] && ![ecpm_str isEqual:@""]) {
        ecpm = [XSHelper str2num:ecpm_str];
    }
    return ecpm;
}

- (int)getInt:(NSString *)key dic:(NSDictionary*)dic {
    NSLog(@"getInt: %@", key);
    id t_idfa = dic[key];
    NSString *ecpm_str = [NSString stringWithFormat:@"%@", t_idfa];
    
    NSNumber *ecpm = @(-99);
    
    if (ecpm_str && ![ecpm_str isEqual:[NSNull null]] && ![ecpm_str isEqual:@""]) {
        ecpm = [XSHelper str2num:ecpm_str];
    }
    return [ecpm intValue];
}

- (void)dealloc {
    [self stop];
}

@end