#import "ReactNativeStraightTableComponentView.h"

#import <react/renderer/components/RNSimpleGridSpec/ComponentDescriptors.h>
#import <react/renderer/components/RNSimpleGridSpec/EventEmitters.h>
#import <react/renderer/components/RNSimpleGridSpec/Props.h>
#import <react/renderer/components/RNSimpleGridSpec/RCTComponentViewHelpers.h>

#import <React/RCTConversions.h>
#import <React/RCTBridge+Private.h>
#import <react/renderer/graphics/Color.h>

#import "react_native_simple_grid-Swift.h"

using namespace facebook::react;

@interface ReactNativeStraightTableComponentView () <RCTReactNativeStraightTableViewViewProtocol>
@end


@implementation ReactNativeStraightTableComponentView {
    ContainerView *_view;
}

+ (ComponentDescriptorProvider)componentDescriptorProvider
{
    return concreteComponentDescriptorProvider<ReactNativeStraightTableViewComponentDescriptor>();
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        static const auto defaultProps = std::make_shared<const ReactNativeStraightTableViewProps>();
        _props = defaultProps;
        
        _view = [[ContainerView alloc] initWithFrame:frame];
      
        __weak ReactNativeStraightTableComponentView *weakSelf = self;
        
        _view.onConfirmSelectionsCallback = ^(NSDictionary *event) {
            if (weakSelf) {
                auto strongSelf = weakSelf;
                if (strongSelf->_eventEmitter) {
                    auto emitter = std::static_pointer_cast<const ReactNativeStraightTableViewEventEmitter>(strongSelf->_eventEmitter);
                    emitter->onConfirmSelections({});
                }
            }
        };

        _view.onEndReachedCallback = ^(NSDictionary *event) {
            if (weakSelf) {
                auto strongSelf = weakSelf;
                if (strongSelf->_eventEmitter) {
                    auto emitter = std::static_pointer_cast<const ReactNativeStraightTableViewEventEmitter>(strongSelf->_eventEmitter);
                    emitter->onEndReached({});
                }
            }
        };
        
        _view.onExpandCellCallback = ^(NSDictionary *event) {
            if (weakSelf) {
                auto strongSelf = weakSelf;
                if (strongSelf->_eventEmitter) {
                    auto emitter = std::static_pointer_cast<const ReactNativeStraightTableViewEventEmitter>(strongSelf->_eventEmitter);
                    std::string row = event[@"row"] ? std::string([event[@"row"] UTF8String]) : "";
                    std::string col = event[@"col"] ? std::string([event[@"col"] UTF8String]) : "";
                    emitter->onExpandCell({.row = row, .col = col});
                }
            }
        };

        _view.onHeaderPressedCallback = ^(NSDictionary *event) {
            if (weakSelf) {
                auto strongSelf = weakSelf;
                if (strongSelf->_eventEmitter) {
                    auto emitter = std::static_pointer_cast<const ReactNativeStraightTableViewEventEmitter>(strongSelf->_eventEmitter);
                    double target = event[@"target"] ? [event[@"target"] doubleValue] : 0.0;
                    NSString *columnJSON = event[@"column"] ? event[@"column"] : @"{}";
                    emitter->onHeaderPressed({.target = target, .column = std::string([columnJSON UTF8String])});
                }
            }
        };
        
        _view.onSelectionsChangedCallback = ^(NSDictionary *event) {
            if (weakSelf) {
                auto strongSelf = weakSelf;
                if (strongSelf->_eventEmitter) {
                    auto emitter = std::static_pointer_cast<const ReactNativeStraightTableViewEventEmitter>(strongSelf->_eventEmitter);
                    
                    // Convert selections array to JSON string
                    NSArray *selectionsArray = event[@"selections"];
                    NSString *selectionsJSON = @"[]";
                    if (selectionsArray && [selectionsArray isKindOfClass:[NSArray class]]) {
                        NSError *error = nil;
                        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:selectionsArray options:0 error:&error];
                        if (!error && jsonData) {
                            selectionsJSON = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
                        }
                    }
                    
                    emitter->onSelectionsChanged({.selections = std::string([selectionsJSON UTF8String])});
                }
            }
        };
        
        _view.onSearchColumnCallback = ^(NSDictionary *event) {
            if (weakSelf) {
                auto strongSelf = weakSelf;
                if (strongSelf->_eventEmitter) {
                    auto emitter = std::static_pointer_cast<const ReactNativeStraightTableViewEventEmitter>(strongSelf->_eventEmitter);
                    double target = event[@"target"] ? [event[@"target"] doubleValue] : 0.0;
                    NSString *columnJSON = event[@"column"] ? event[@"column"] : @"{}";
                    emitter->onSearchColumn({.target = target, .column = std::string([columnJSON UTF8String])});
                }
            }
        };
        
        self.contentView = _view;
    }
    
    return self;
}

- (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &)oldProps
{
    const auto &oldViewProps = *std::static_pointer_cast<const ReactNativeStraightTableViewProps>(_props);
    const auto &newViewProps = *std::static_pointer_cast<const ReactNativeStraightTableViewProps>(props);
    
    // CellContentStyle
    {
        NSMutableDictionary *cellContentStyle = [NSMutableDictionary new];
        
        if (!newViewProps.cellContentStyle.borderColor.empty()) {
            cellContentStyle[@"borderColor"] = RCTNSStringFromString(newViewProps.cellContentStyle.borderColor);
        }
        if (!newViewProps.cellContentStyle.borderStyle.empty()) {
            cellContentStyle[@"borderStyle"] = RCTNSStringFromString(newViewProps.cellContentStyle.borderStyle);
        }
        if (!newViewProps.cellContentStyle.borderWidth.empty()) {
            cellContentStyle[@"borderWidth"] = RCTNSStringFromString(newViewProps.cellContentStyle.borderWidth);
        }
        if (!newViewProps.cellContentStyle.color.empty()) {
            cellContentStyle[@"color"] = RCTNSStringFromString(newViewProps.cellContentStyle.color);
        }
        if (!newViewProps.cellContentStyle.fontFamily.empty()) {
            cellContentStyle[@"fontFamily"] = RCTNSStringFromString(newViewProps.cellContentStyle.fontFamily);
        }
        cellContentStyle[@"fontSize"] = @(newViewProps.cellContentStyle.fontSize);
        if (!newViewProps.cellContentStyle.hoverBackgroundColor.empty()) {
            cellContentStyle[@"hoverBackgroundColor"] = RCTNSStringFromString(newViewProps.cellContentStyle.hoverBackgroundColor);
        } else {
          cellContentStyle[@"hoverBackgroundColor"] = RCTNSStringFromString("inherit");
        }
        if (!newViewProps.cellContentStyle.hoverFontColor.empty()) {
            cellContentStyle[@"hoverFontColor"] = RCTNSStringFromString(newViewProps.cellContentStyle.hoverFontColor);
        }
        cellContentStyle[@"rowHeight"] = @(newViewProps.cellContentStyle.rowHeight);
        cellContentStyle[@"wrap"] = @(newViewProps.cellContentStyle.wrap);
        
        _view.cellContentStyle = cellContentStyle;
    }

     // ClearSelections
    if (oldViewProps.clearSelections != newViewProps.clearSelections) {
        _view.clearSelections = RCTNSStringFromString(newViewProps.clearSelections);
    }
    
    // Cols
    {
        NSMutableDictionary *cols = [NSMutableDictionary new];
        NSMutableArray *header = [NSMutableArray new];

        
        for (const auto &col : newViewProps.cols.header) {
            NSMutableDictionary *colDict = [NSMutableDictionary new];
            if(!col.id.empty()) {
                colDict[@"id"] = RCTNSStringFromString(col.id);
            }
            colDict[@"active"] = @(col.active);
            if (!col.align.empty()) {
                colDict[@"align"] = RCTNSStringFromString(col.align);
            }
            colDict[@"dataColIdx"] = @(col.dataColIdx);
            colDict[@"isDim"] = @(col.isDim);
            if (!col.label.empty()) {
                colDict[@"label"] = RCTNSStringFromString(col.label);
            }
            
            //Representation
            {
                NSMutableDictionary *representation = [NSMutableDictionary new];
                representation[@"imageLabel"] = !col.representation.imageLabel.empty() ? RCTNSStringFromString(col.representation.imageLabel) : @"";
                representation[@"imagePosition"] = !col.representation.imagePosition.empty() ? RCTNSStringFromString(col.representation.imagePosition) : @"";
                representation[@"imageSetting"] = !col.representation.imageSetting.empty() ? RCTNSStringFromString(col.representation.imageSetting) : @"";
                representation[@"imageSize"] = !col.representation.imageSize.empty() ? RCTNSStringFromString(col.representation.imageSize) : @"";
                representation[@"imageUrl"] = !col.representation.imageUrl.empty() ? RCTNSStringFromString(col.representation.imageUrl) : @"";
                representation[@"linkUrl"] = !col.representation.linkUrl.empty() ? RCTNSStringFromString(col.representation.linkUrl) : @"";
                representation[@"type"] = !col.representation.type.empty() ? RCTNSStringFromString(col.representation.type) : @"";
                representation[@"urlLabel"] = !col.representation.urlLabel.empty() ? RCTNSStringFromString(col.representation.urlLabel) : @"";
                representation[@"urlPosition"] = !col.representation.urlPosition.empty() ? RCTNSStringFromString(col.representation.urlPosition) : @"";
                
                colDict[@"representation"] = representation;
            }
            
            if (!col.sortDirection.empty()) {
                colDict[@"sortDirection"] = RCTNSStringFromString(col.sortDirection);
            }
            
            // StylingInfo - always include even if empty
            NSMutableArray *stylingInfoArray = [NSMutableArray new];
            for (const auto &info : col.stylingInfo) {
                if (!info.empty()) {
                    [stylingInfoArray addObject:RCTNSStringFromString(info)];
                }
            }
            colDict[@"stylingInfo"] = stylingInfoArray;
            
            if (!col.totalInfo.empty()) {
                colDict[@"totalInfo"] = RCTNSStringFromString(col.totalInfo);
            }
            colDict[@"width"] = @(col.width);
            
            [header addObject:colDict];
        }
        
        cols[@"header"] = header;
        
        // Footer
        NSMutableArray *footer = [NSMutableArray new];
        for (const auto &footerCell : newViewProps.cols.footer) {
            NSMutableDictionary *footerDict = [NSMutableDictionary new];
            if (!footerCell.qText.empty()) {
                footerDict[@"qText"] = RCTNSStringFromString(footerCell.qText);
            }
            footerDict[@"qNum"] = @(footerCell.qNum);
            footerDict[@"qElemNumber"] = @(footerCell.qElemNumber);
            if (!footerCell.qState.empty()) {
                footerDict[@"qState"] = RCTNSStringFromString(footerCell.qState);
            }
            footerDict[@"qIsTotalCell"] = @(footerCell.qIsTotalCell);
            [footer addObject:footerDict];
        }
        cols[@"footer"] = footer;
        
        // Totals
        {
            const auto &totalsField = newViewProps.cols.totals;
            const bool hasTotals = totalsField.show ||
                !totalsField.label.empty() ||
                !totalsField.rows.empty() ||
                !totalsField.values.empty();
            
            if (hasTotals) {
                NSMutableDictionary *totals = [NSMutableDictionary new];
                totals[@"show"] = @(totalsField.show);
                if (!totalsField.label.empty()) {
                    totals[@"label"] = RCTNSStringFromString(totalsField.label);
                }
                NSMutableArray *rows = [NSMutableArray new];
                for (const auto &rowCell : totalsField.rows) {
                    NSMutableDictionary *rowDict = [NSMutableDictionary new];
                    if (!rowCell.qText.empty()) {
                        rowDict[@"qText"] = RCTNSStringFromString(rowCell.qText);
                    }
                    rowDict[@"qNum"] = @(rowCell.qNum);
                    rowDict[@"qElemNumber"] = @(rowCell.qElemNumber);
                    if (!rowCell.qState.empty()) {
                        rowDict[@"qState"] = RCTNSStringFromString(rowCell.qState);
                    }
                    rowDict[@"qIsTotalCell"] = @(rowCell.qIsTotalCell);
                    [rows addObject:rowDict];
                }
                totals[@"rows"] = rows;
                NSMutableArray *values = [NSMutableArray new];
                for (const auto &value : totalsField.values) {
                    [values addObject:value.empty() ? @"" : RCTNSStringFromString(value)];
                }
                if(!totalsField.position.empty()) {
                    totals[@"position"] = RCTNSStringFromString(totalsField.position);
                }
                totals[@"values"] = values;
                cols[@"totals"] = totals;
            }
        }
        
        _view.cols = cols;
    }

    // ContainerWidth
    if (oldViewProps.containerWidth != newViewProps.containerWidth) {
        _view.containerWidth = @(newViewProps.containerWidth);
    }

    // FreezeFirstColumn
    if (oldViewProps.freezeFirstColumn != newViewProps.freezeFirstColumn) {
        _view.freezeFirstColumn = newViewProps.freezeFirstColumn;
    }
    
    // HeaderContentStyle
    {
        NSMutableDictionary *headerContentStyle = [NSMutableDictionary new];
        
        if (!newViewProps.headerContentStyle.backgroundColor.empty()) {
            headerContentStyle[@"backgroundColor"] = RCTNSStringFromString(newViewProps.headerContentStyle.backgroundColor);
        }
        if (!newViewProps.headerContentStyle.borderColor.empty()) {
            headerContentStyle[@"borderColor"] = RCTNSStringFromString(newViewProps.headerContentStyle.borderColor);
        }
        if (!newViewProps.headerContentStyle.borderStyle.empty()) {
            headerContentStyle[@"borderStyle"] = RCTNSStringFromString(newViewProps.headerContentStyle.borderStyle);
        }
        if (!newViewProps.headerContentStyle.borderWidth.empty()) {
            headerContentStyle[@"borderWidth"] = RCTNSStringFromString(newViewProps.headerContentStyle.borderWidth);
        }
        if (!newViewProps.headerContentStyle.color.empty()) {
            headerContentStyle[@"color"] = RCTNSStringFromString(newViewProps.headerContentStyle.color);
        }
        if(!newViewProps.headerContentStyle.cursor.empty()) {
            headerContentStyle[@"cursor"] = RCTNSStringFromString(newViewProps.headerContentStyle.cursor);
        }
        if (!newViewProps.headerContentStyle.fontFamily.empty()) {
            headerContentStyle[@"fontFamily"] = RCTNSStringFromString(newViewProps.headerContentStyle.fontFamily);
        }
        headerContentStyle[@"fontSize"] = @(newViewProps.headerContentStyle.fontSize);
        if(!newViewProps.headerContentStyle.sortLabelColor.empty()) {
            headerContentStyle[@"sortLabelColor"] = RCTNSStringFromString(newViewProps.headerContentStyle.sortLabelColor);
        }
        headerContentStyle[@"wrap"] = @(newViewProps.headerContentStyle.wrap);
        _view.headerContentStyle = headerContentStyle;
    }

     // IsDataView
    if (oldViewProps.isDataView != newViewProps.isDataView) {
        _view.isDataView = newViewProps.isDataView;
    }

    // Name
    if (oldViewProps.name != newViewProps.name) {
        _view.name = !newViewProps.name.empty() ? RCTNSStringFromString(newViewProps.name) : nil;
    }

    // Rows - Parse JSON to get dynamic col-* keys
    {
        NSMutableDictionary *rows = [NSMutableDictionary new];
        NSMutableArray *rowsArray = [NSMutableArray new];
        
        // Parse rowsJSON string to get full row objects with dynamic col-* keys
        if (!newViewProps.rows.rowsJSON.empty()) {
            NSString *jsonString = RCTNSStringFromString(newViewProps.rows.rowsJSON);
            NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
            if (jsonData) {
                NSError *error = nil;
                id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
                if (!error && [jsonObject isKindOfClass:[NSArray class]]) {
                    rowsArray = [(NSArray *)jsonObject mutableCopy];
                }
            }
        }
        
        rows[@"rows"] = rowsArray;
        rows[@"reset"] = @(newViewProps.rows.reset);
        _view.rows = rows;
    }
    
    // Size
    if (oldViewProps.size.qcx != newViewProps.size.qcx || 
        oldViewProps.size.qcy != newViewProps.size.qcy) {
        NSMutableDictionary *size = [NSMutableDictionary new];
        size[@"qcx"] = @(newViewProps.size.qcx);
        size[@"qcy"] = @(newViewProps.size.qcy);
        _view.size = size;
    }
    
     // Theme
    {
        NSMutableDictionary *theme = [NSMutableDictionary new];
        
        if (!newViewProps.theme.backgroundColor.empty()) {
            theme[@"backgroundColor"] = RCTNSStringFromString(newViewProps.theme.backgroundColor);
        }
        if (!newViewProps.theme.borderBackgroundColor.empty()) {
            theme[@"borderBackgroundColor"] = RCTNSStringFromString(newViewProps.theme.borderBackgroundColor);
        }
        theme[@"borderRadius"] = @(newViewProps.theme.borderRadius);
        if (!newViewProps.theme.borderSelectedColor.empty()) {
            theme[@"borderSelectedColor"] = RCTNSStringFromString(newViewProps.theme.borderSelectedColor);
        }
        if (!newViewProps.theme.even.empty()) {
            theme[@"even"] = RCTNSStringFromString(newViewProps.theme.even);
        }
        if (!newViewProps.theme.headerBackgroundColor.empty()) {
            theme[@"headerBackgroundColor"] = RCTNSStringFromString(newViewProps.theme.headerBackgroundColor);
        }
        theme[@"headerHeight"] = @(newViewProps.theme.headerHeight);
        if (!newViewProps.theme.headerTextColor.empty()) {
            theme[@"headerTextColor"] = RCTNSStringFromString(newViewProps.theme.headerTextColor);
        }
        theme[@"rowHeight"] = @(newViewProps.theme.rowHeight);
        if (!newViewProps.theme.selectedBackground.empty()) {
            theme[@"selectedBackground"] = RCTNSStringFromString(newViewProps.theme.selectedBackground);
        }
        _view.theme = theme;
    }

    // Translations
    {
        NSMutableDictionary *translations = [NSMutableDictionary new];
       
       // Menu
       { 
            NSMutableDictionary *menu = [NSMutableDictionary new];

            if (!newViewProps.translations.menu.copy.empty()) {
                menu[@"copy"] = RCTNSStringFromString(newViewProps.translations.menu.copy);
            }
            if (!newViewProps.translations.menu.expand.empty()) {
                menu[@"expand"] = RCTNSStringFromString(newViewProps.translations.menu.expand);
            }
            if (!newViewProps.translations.menu.share.empty()) {
                menu[@"share"] = RCTNSStringFromString(newViewProps.translations.menu.share);
            }
            translations[@"menu"] = menu;
       }

       // Misc
       {
            NSMutableDictionary *misc = [NSMutableDictionary new];

            if (!newViewProps.translations.misc.of.empty()) {
                misc[@"of"] = RCTNSStringFromString(newViewProps.translations.misc.of);
            }
            translations[@"misc"] = misc;
       }

       // HeaderValues
       {
            NSMutableArray *headerValues = [NSMutableArray new];

            for (const auto &headerValue : newViewProps.translations.headerValues) {
                if (!headerValue.empty()) {
                    [headerValues addObject:RCTNSStringFromString(headerValue)];
                }

            }
            translations[@"headerValues"] = headerValues;
       }
       _view.translations = translations;

    }

    [super updateProps:props oldProps:oldProps];
}

Class<RCTComponentViewProtocol> ReactNativeStraightTableViewCls(void)
{
    return ReactNativeStraightTableComponentView.class;
}

@end
