//
//  CameraUtility.m
//  AIIM
//
//  Created by qitewei on 2025/6/5.
//

#import "CameraUtility.h"

// 默认视频保存路径
#define DEFAULT_VIDEO_DIRECTORY @"Videos"

@interface CameraUtility () <AVCaptureFileOutputRecordingDelegate, AVCapturePhotoCaptureDelegate>{
    NSURL *_lastVideoOutputURL;
}

@property (nonatomic, strong) AVCaptureSession *captureSession;
@property (nonatomic, strong) AVCaptureDeviceInput *videoInput;
@property (nonatomic, strong) AVCapturePhotoOutput *photoOutput;
@property (nonatomic, strong) AVCaptureMovieFileOutput *movieFileOutput;

@property (nonatomic, weak) UIView *previewView;
@property (nonatomic, strong) NSTimer *progressTimer;
@property (nonatomic, assign) CGFloat recordingDuration;
@property (nonatomic, assign) BOOL isRecording;

@end

@implementation CameraUtility

static const CGFloat kMaxVideoDuration = 60.0f; // 最大录制时长60秒

#pragma mark - 生命周期方法

- (instancetype)initWithPreviewView:(UIView *)previewView {
    self = [super init];
    if (self) {
        _previewView = previewView;
        _flashMode = CameraUtilityFlashModeOff;
        _isFrontCamera = NO;
        _recordingDuration = 0;
        _isRecording = NO;
        
        [self setupCaptureSession];
    }
    return self;
}

- (void)dealloc {
    [self stopRunning];
    [self cleanTempFiles];
}

#pragma mark - 公开方法

- (void)configureCaptureButton:(UIButton *)button {
    // 单击手势 - 拍照
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
    tapGesture.numberOfTapsRequired = 1;
    [button addGestureRecognizer:tapGesture];
    
    // 长按手势 - 拍视频
    UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressGesture:)];
    longPressGesture.minimumPressDuration = 0.3;
    [button addGestureRecognizer:longPressGesture];
    
    // 确保单击不会被长按阻塞
    [tapGesture requireGestureRecognizerToFail:longPressGesture];
}

- (void)startRunning {
    if (![self.captureSession isRunning]) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self.captureSession startRunning];
        });
    }
}

- (void)stopRunning {
    if ([self.captureSession isRunning]) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            [self.captureSession stopRunning];
        });
    }
}

- (void)switchCamera {
    AVCaptureDevicePosition position = self.isFrontCamera ? AVCaptureDevicePositionBack : AVCaptureDevicePositionFront;
    AVCaptureDevice *device = [self cameraWithPosition:position];
    
    if (!device) return;
    
    [self.captureSession beginConfiguration];
    
    // 移除原有输入
    [self.captureSession removeInput:self.videoInput];
    
    // 创建新输入
    NSError *error = nil;
    AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:device error:&error];
    
    if (newVideoInput) {
        if ([self.captureSession canAddInput:newVideoInput]) {
            [self.captureSession addInput:newVideoInput];
            self.videoInput = newVideoInput;
            self.isFrontCamera = !self.isFrontCamera;
        }
    } else {
        if ([self.delegate respondsToSelector:@selector(cameraUtilityDidOccurError:)]) {
            [self.delegate cameraUtilityDidOccurError:error];
        }
    }
    
    [self.captureSession commitConfiguration];
    
    // 重新设置闪光灯模式
    [self setFlashMode:self.flashMode];
}

- (void)takePhoto {
    AVCaptureConnection *connection = [self.photoOutput connectionWithMediaType:AVMediaTypeVideo];
        
    if (connection.isVideoOrientationSupported) {
        connection.videoOrientation = [self currentVideoOrientation];
    }
    
    // 创建照片设置
    AVCapturePhotoSettings *photoSettings;
    
    if (@available(iOS 11.0, *)) {
        // iOS 11+ 使用正确的格式设置
        NSDictionary *format = @{
            AVVideoCodecKey: AVVideoCodecTypeJPEG,
            AVVideoCompressionPropertiesKey: @{
                AVVideoQualityKey: @0.9  // 质量参数放在压缩属性字典内
            }
        };
        photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:format];
    } else {
        // iOS 10 回退方案
        photoSettings = [AVCapturePhotoSettings photoSettings];
    }
    
    // 设置闪光灯模式
    photoSettings.flashMode = (AVCaptureFlashMode)self.flashMode;
    
    // 触发拍照
    [self.photoOutput capturePhotoWithSettings:photoSettings delegate:self];
}

- (void)startRecordingVideo {
    if (self.isRecording) return;
    
    NSURL *outputURL = [self videoOutputURL];
    
    // 如果文件已存在则删除
    if ([[NSFileManager defaultManager] fileExistsAtPath:outputURL.path]) {
        [[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
    }
    
    AVCaptureConnection *connection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    if (connection.isVideoOrientationSupported) {
        connection.videoOrientation = [self currentVideoOrientation];
    }
    
    [self.movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
    
    self.isRecording = YES;
    self.recordingDuration = 0;
    
    self.progressTimer = [NSTimer scheduledTimerWithTimeInterval:0.05
                                                          target:self
                                                        selector:@selector(updateRecordingProgress)
                                                        userInfo:nil
                                                         repeats:YES];
}

- (void)stopRecordingVideo {
    if (!self.isRecording) return;
    
    [self.movieFileOutput stopRecording];
    [self.progressTimer invalidate];
    self.progressTimer = nil;
    self.isRecording = NO;
}

- (void)cleanTempFiles {
    NSString *tempPath = NSTemporaryDirectory();
    NSArray *contents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tempPath error:nil];
    
    for (NSString *file in contents) {
        if ([file hasPrefix:@"tempVideo"] && [file hasSuffix:@".mp4"]) {
            NSString *filePath = [tempPath stringByAppendingPathComponent:file];
            [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
        }
    }
}

#pragma mark - 私有方法

- (void)setupCaptureSession {
    self.captureSession = [[AVCaptureSession alloc] init];
    
    // 根据设备性能选择合适的分辨率
    if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset3840x2160]) {
        self.captureSession.sessionPreset = AVCaptureSessionPreset3840x2160;
    } else if ([self.captureSession canSetSessionPreset:AVCaptureSessionPreset1920x1080]) {
        self.captureSession.sessionPreset = AVCaptureSessionPreset1920x1080;
    } else {
        self.captureSession.sessionPreset = AVCaptureSessionPreset1280x720;
    }
    
    // 设置视频输入
    AVCaptureDevice *videoDevice = [self cameraWithPosition:AVCaptureDevicePositionBack];
    if (!videoDevice) {
        if ([self.delegate respondsToSelector:@selector(cameraUtilityDidOccurError:)]) {
            NSError *error = [NSError errorWithDomain:@"CameraUtility" code:1001 userInfo:@{NSLocalizedDescriptionKey: @"无法获取摄像头设备"}];
            [self.delegate cameraUtilityDidOccurError:error];
        }
        return;
    }
    
    NSError *error = nil;
    self.videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoDevice error:&error];
    
    if (error) {
        if ([self.delegate respondsToSelector:@selector(cameraUtilityDidOccurError:)]) {
            [self.delegate cameraUtilityDidOccurError:error];
        }
        return;
    }
    
    if ([self.captureSession canAddInput:self.videoInput]) {
        [self.captureSession addInput:self.videoInput];
    }
    
    // 设置音频输入
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    AVCaptureDeviceInput *audioInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:&error];
    
    if (!error && [self.captureSession canAddInput:audioInput]) {
        [self.captureSession addInput:audioInput];
    }
    
    // 设置照片输出
    self.photoOutput = [[AVCapturePhotoOutput alloc] init];
    
    // 检查是否支持高质量照片捕获
    if ([self.photoOutput isHighResolutionCaptureEnabled]) {
        self.photoOutput.highResolutionCaptureEnabled = YES;
    }
    
    if ([self.captureSession canAddOutput:self.photoOutput]) {
        [self.captureSession addOutput:self.photoOutput];
    }
    
    // 设置视频文件输出
    self.movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
    
    // 设置最大录制时长
    CMTime maxDuration = CMTimeMakeWithSeconds(kMaxVideoDuration, 1);
    self.movieFileOutput.maxRecordedDuration = maxDuration;
    
    if ([self.captureSession canAddOutput:self.movieFileOutput]) {
        [self.captureSession addOutput:self.movieFileOutput];
    }
    
    // 设置预览层
    self.previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
    self.previewLayer.frame = self.previewView.bounds;
    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    [self.previewView.layer insertSublayer:self.previewLayer atIndex:0];
}

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position {
    if (@available(iOS 10.0, *)) {
        AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:position];
        return discoverySession.devices.firstObject;
    } else {
        // iOS 10 以下版本的兼容代码
        NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for (AVCaptureDevice *device in devices) {
            if (device.position == position) {
                return device;
            }
        }
        return nil;
    }
}

- (AVCaptureVideoOrientation)currentVideoOrientation {
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    
    switch (orientation) {
        case UIInterfaceOrientationPortrait:
            return AVCaptureVideoOrientationPortrait;
        case UIInterfaceOrientationLandscapeLeft:
            return AVCaptureVideoOrientationLandscapeLeft;
        case UIInterfaceOrientationLandscapeRight:
            return AVCaptureVideoOrientationLandscapeRight;
        case UIInterfaceOrientationPortraitUpsideDown:
            return AVCaptureVideoOrientationPortraitUpsideDown;
        default:
            return AVCaptureVideoOrientationPortrait;
    }
}

- (NSString *)tempVideoFilePath {
    NSString *tempPath = NSTemporaryDirectory();
    NSString *fileName = [NSString stringWithFormat:@"tempVideo_%@.mp4", [[NSUUID UUID] UUIDString]];
    return [tempPath stringByAppendingPathComponent:fileName];
}

- (void)setFlashMode:(CameraUtilityFlashMode)flashMode {
    _flashMode = flashMode;
    
    AVCaptureDevice *device = self.videoInput.device;
    if ([device hasFlash] && [[self.photoOutput supportedFlashModes] containsObject:[NSNumber numberWithInteger:flashMode]]) {
        NSError *error = nil;
        if ([device lockForConfiguration:&error]) {
            self.photoOutput.photoSettingsForSceneMonitoring.flashMode = (AVCaptureFlashMode)flashMode;
//            device.flashMode = (AVCaptureFlashMode)flashMode;
            [device unlockForConfiguration];
        } else {
            if ([self.delegate respondsToSelector:@selector(cameraUtilityDidOccurError:)]) {
                [self.delegate cameraUtilityDidOccurError:error];
            }
        }
    }
}

- (void)updateRecordingProgress {
    if (!self.isRecording) return;
    
    self.recordingDuration += 0.05;
    CGFloat progress = self.recordingDuration / kMaxVideoDuration;
    
    if (progress >= 1.0) {
        [self stopRecordingVideo];
        progress = 1.0;
    }
    
    if ([self.delegate respondsToSelector:@selector(cameraUtilityRecordingProgress:)]) {
        [self.delegate cameraUtilityRecordingProgress:progress];
    }
}

- (UIImage *)adjustImageToScreenRatio:(UIImage *)image {
    if (self.aspectRatioMode == CameraAspectRatioModeOriginal) {
        return image;
    }
    
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    CGFloat screenRatio = screenSize.width / screenSize.height;
    CGSize imageSize = image.size;
    CGFloat imageRatio = imageSize.width / imageSize.height;
    
    // 计算目标尺寸
    CGSize targetSize;
    if (self.aspectRatioMode == CameraAspectRatioModeSquare) {
        CGFloat size = MIN(imageSize.width, imageSize.height);
        targetSize = CGSizeMake(size, size);
    } else {
        if (imageRatio > screenRatio) {
            // 图片比屏幕宽，以高度为基准
            targetSize = CGSizeMake(imageSize.height * screenRatio, imageSize.height);
        } else {
            // 图片比屏幕高，以宽度为基准
            targetSize = CGSizeMake(imageSize.width, imageSize.width / screenRatio);
        }
    }
    
    // 高性能裁剪方法
    return [self cropImage:image toRect:CGRectMake(
        (imageSize.width - targetSize.width)/2,
        (imageSize.height - targetSize.height)/2,
        targetSize.width,
        targetSize.height
    )];
}

- (UIImage *)cropImage:(UIImage *)image toRect:(CGRect)rect {
    // 转换为像素精确坐标
    rect = CGRectMake(rect.origin.x * image.scale,
                     rect.origin.y * image.scale,
                     rect.size.width * image.scale,
                     rect.size.height * image.scale);
    
    CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, rect);
    UIImage *result = [UIImage imageWithCGImage:imageRef
                                         scale:image.scale
                                   orientation:image.imageOrientation];
    CGImageRelease(imageRef);
    return result;
}

- (UIImage *)safeCropImageToScreenRatio:(UIImage *)originalImage {
    // 先校正方向
    UIImage *normalizedImage = [self correctedImage:originalImage];
    
    // 现在获取的尺寸是显示方向正确的尺寸
    CGSize imageSize = normalizedImage.size;
    CGFloat imageRatio = imageSize.width / imageSize.height;
    
    // 获取屏幕比例（注意考虑界面当前方向）
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    CGFloat screenRatio = screenSize.width / screenSize.height;
    
    // 计算裁剪区域（基于校正后的图像）
    CGRect cropRect;
    if (imageRatio > screenRatio) {
        // 裁剪宽度
        CGFloat newWidth = imageSize.height * screenRatio;
        cropRect = CGRectMake((imageSize.width - newWidth)/2, 0, newWidth, imageSize.height);
    } else {
        // 裁剪高度
        CGFloat newHeight = imageSize.width / screenRatio;
        cropRect = CGRectMake(0, (imageSize.height - newHeight)/2, imageSize.width, newHeight);
    }
    
    // 执行裁剪
    return [self cropImage:normalizedImage toRect:cropRect];
}

- (UIImage *)correctedImage:(UIImage *)image {
    if (image.imageOrientation == UIImageOrientationUp) return image;
    
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
    UIImage *normalizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return normalizedImage;
}

#pragma mark - 手势处理

- (void)handleTapGesture:(UITapGestureRecognizer *)gesture {
    if (gesture.state == UIGestureRecognizerStateEnded) {
        [self takePhoto];
    }
}

- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)gesture {
    switch (gesture.state) {
        case UIGestureRecognizerStateBegan:
            [self startRecordingVideo];
            break;
            
        case UIGestureRecognizerStateEnded:
        case UIGestureRecognizerStateCancelled:
        case UIGestureRecognizerStateFailed:
            [self stopRecordingVideo];
            break;
            
        default:
            break;
    }
}

#pragma mark - AVCapturePhotoCaptureDelegate

- (void)captureOutput:(AVCapturePhotoOutput *)output
didFinishProcessingPhoto:(AVCapturePhoto *)photo
                error:(NSError *)error {
    if (error) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.delegate cameraUtilityDidOccurError:error];
        });
        return;
    }
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *imageData = [photo fileDataRepresentation];
        UIImage *image = [UIImage imageWithData:imageData];
        
        // 在后台线程处理图片
        image = [self safeCropImageToScreenRatio:image];
        
        if (self.isFrontCamera) {
            image = [UIImage imageWithCGImage:image.CGImage
                                        scale:image.scale
                                  orientation:UIImageOrientationLeftMirrored];
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.delegate cameraUtilityDidFinishTakingPhoto:image];
        });
    });
    
}

#pragma mark - AVCaptureFileOutputRecordingDelegate

- (void)captureOutput:(AVCaptureFileOutput *)output
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
      fromConnections:(NSArray<AVCaptureConnection *> *)connections
                error:(NSError *)error {
    [self.progressTimer invalidate];
    self.progressTimer = nil;
    self.isRecording = NO;
    
    if (error) {
        // 删除可能不完整的视频文件
        if ([[NSFileManager defaultManager] fileExistsAtPath:outputFileURL.path]) {
            [[NSFileManager defaultManager] removeItemAtURL:outputFileURL error:nil];
        }
        
        if ([self.delegate respondsToSelector:@selector(cameraUtilityDidOccurError:)]) {
            [self.delegate cameraUtilityDidOccurError:error];
        }
        return;
    }
    
    // 确保文件已保存
    if ([[NSFileManager defaultManager] fileExistsAtPath:outputFileURL.path]) {
        _lastVideoOutputURL = outputFileURL;
        
        if ([self.delegate respondsToSelector:@selector(cameraUtilityDidFinishRecordingVideo:)]) {
            [self.delegate cameraUtilityDidFinishRecordingVideo:outputFileURL];
        }
    } else {
        NSError *fileError = [NSError errorWithDomain:@"CameraUtility"
                                                 code:1001
                                             userInfo:@{NSLocalizedDescriptionKey: @"视频文件保存失败"}];
        if ([self.delegate respondsToSelector:@selector(cameraUtilityDidOccurError:)]) {
            [self.delegate cameraUtilityDidOccurError:fileError];
        }
    }
}

#pragma mark - 视频路径处理

- (NSString *)videoSaveDirectory {
    if (!_videoSaveDirectory) {
        _videoSaveDirectory = DEFAULT_VIDEO_DIRECTORY;
    }
    return _videoSaveDirectory;
}

- (NSURL *)lastVideoOutputURL {
    return _lastVideoOutputURL;
}

// 获取视频保存路径
- (NSURL *)videoOutputURL {
    NSString *fileName = [NSString stringWithFormat:@"video_%@.mp4", [NSUUID UUID].UUIDString];
    
    // 获取文档目录
    NSURL *documentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
    NSURL *videoDirURL = [documentsURL URLByAppendingPathComponent:self.videoSaveDirectory isDirectory:YES];
    
    // 创建目录（如果不存在）
    [[NSFileManager defaultManager] createDirectoryAtURL:videoDirURL
                            withIntermediateDirectories:YES
                                             attributes:nil
                                                  error:nil];
    
    _lastVideoOutputURL = [videoDirURL URLByAppendingPathComponent:fileName];
    return _lastVideoOutputURL;
}

@end
