//  SyncHistoryViewController.mm

#import "SyncHistoryViewController.h"
#import "OfflineSyncManager.h"
#import "SyncProgressOverlay.h"
#import "HistoryDetailsViewController.h"

typedef NS_ENUM(NSInteger, HistorySyncStatus) {
    HistorySyncStatusSuccess,
    HistorySyncStatusFailed
};

@interface HistorySyncItem : NSObject
@property (nonatomic, strong) NSString *unitName;
@property (nonatomic, strong) NSString *createdBy;
@property (nonatomic, strong) NSString *createdOn;
@property (nonatomic, strong) NSString *uploadedOn;
@property (nonatomic, strong) NSString *actionMade;
@property (nonatomic, assign) HistorySyncStatus status;
@property (nonatomic, strong) NSDictionary *raw;
@end

@implementation HistorySyncItem
@end

@interface HistorySyncCell : UITableViewCell

- (void)configureWithItem:(HistorySyncItem *)item;

@end

@interface HistorySyncCell ()

@property (nonatomic, strong) UILabel *unitLabel;
@property (nonatomic, strong) UILabel *createdByLabel;
@property (nonatomic, strong) UILabel *createdOnLabel;
@property (nonatomic, strong) UILabel *uploadedOnLabel;
@property (nonatomic, strong) UILabel *actionLabel;

@end

@implementation HistorySyncCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style
              reuseIdentifier:(NSString *)reuseIdentifier {

    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (!self) return nil;

    self.selectionStyle = UITableViewCellSelectionStyleDefault;
    self.backgroundColor = UIColor.clearColor; // 👈 important

    self.contentView.backgroundColor = UIColor.whiteColor;
    self.contentView.layer.cornerRadius = 10;
    self.contentView.layer.masksToBounds = YES;

    self.contentView.layer.borderWidth = 1.0;
    self.contentView.layer.borderColor = [UIColor colorWithWhite:0.85 alpha:1.0].CGColor;

    // 👇 spacing between cards
    self.contentView.layoutMargins = UIEdgeInsetsMake(8, 12, 8, 12);

    [self setupUI];
    return self;
}


- (void)setupUI {

    self.unitLabel = [self labelBold:16];
    self.createdByLabel = [self labelRegular:13];
    self.createdOnLabel = [self labelRegular:13];
    self.uploadedOnLabel = [self labelRegular:13];
    self.actionLabel = [self labelRegular:13];

    UIStackView *stack = [[UIStackView alloc] initWithArrangedSubviews:@[
        self.unitLabel,
        self.createdByLabel,
        self.createdOnLabel,
        self.uploadedOnLabel,
        self.actionLabel
    ]];

    stack.axis = UILayoutConstraintAxisVertical;
    stack.spacing = 4;
    stack.translatesAutoresizingMaskIntoConstraints = NO;

    [self.contentView addSubview:stack];

    [NSLayoutConstraint activateConstraints:@[
        [stack.topAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.topAnchor],
        [stack.leadingAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.leadingAnchor],
        [stack.trailingAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.trailingAnchor],
        [stack.bottomAnchor constraintEqualToAnchor:self.contentView.layoutMarginsGuide.bottomAnchor],
    ]];
}

- (UILabel *)labelBold:(CGFloat)size {
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont boldSystemFontOfSize:size];
    label.textColor = UIColor.blackColor;
    label.numberOfLines = 0;
    return label;
}

- (UILabel *)labelRegular:(CGFloat)size {
    UILabel *label = [[UILabel alloc] init];
    label.font = [UIFont systemFontOfSize:size];
    label.textColor = UIColor.darkGrayColor;
    label.numberOfLines = 0;
    return label;
}

- (void)configureWithItem:(HistorySyncItem *)item {
    self.unitLabel.text = item.unitName;
    self.createdByLabel.text = [NSString stringWithFormat:@"Created by: %@", item.createdBy];
    self.createdOnLabel.text = [NSString stringWithFormat:@"Created on: %@", item.createdOn];
    self.uploadedOnLabel.text = [NSString stringWithFormat:@"Uploaded on: %@", item.uploadedOn];
    self.actionLabel.text = [NSString stringWithFormat:@"Action made: %@", item.actionMade];
}

@end

@interface SyncHistoryViewController () <UITableViewDelegate, UITableViewDataSource>

@property (nonatomic, strong) UIView *headerView;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *shareButton;

@property (nonatomic, strong) UIView *offlineBanner;

@property (nonatomic, strong) UIView *tabBarView;
@property (nonatomic, strong) UIButton *allTabButton;
@property (nonatomic, strong) UIButton *successTabButton;
@property (nonatomic, strong) UIButton *failedTabButton;

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) UIView *emptyStateView;
@property (nonatomic, strong) UIButton *syncAgainButton;

@property (nonatomic, strong) NSArray<HistorySyncItem *> *allItems;
@property (nonatomic, strong) NSArray<HistorySyncItem *> *filteredItems;

@property (nonatomic, assign) NSInteger selectedTab;

@property (nonatomic, strong) SyncProgressOverlay *progressOverlay;
@end

@implementation SyncHistoryViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
    self.selectedTab = 0;

    [self setupHeader];
//    [self setupOfflineBanner];
    [self setupTabBar];
    [self setupBottomButton];
    [self setupTableView];
    [self setupEmptyState];

    [self loadHistoryData];
    [self applyFilter];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self loadHistoryData];
    [self applyFilter];
}

#pragma mark - Header
- (void)setupHeader {
    self.headerView = [[UIView alloc] init];
    self.headerView.backgroundColor = [UIColor colorWithRed:0.0 green:0.5 blue:0.6 alpha:1.0];
    self.headerView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.headerView];

    self.backButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.backButton setImage:[UIImage systemImageNamed:@"chevron.backward"]
                     forState:UIControlStateNormal];
    self.backButton.tintColor = UIColor.whiteColor;
    [self.backButton addTarget:self
                        action:@selector(onBack)
              forControlEvents:UIControlEventTouchUpInside];
    self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
    [self.headerView addSubview:self.backButton];

    self.titleLabel = [[UILabel alloc] init];
    self.titleLabel.text = @"History";
    self.titleLabel.textColor = UIColor.whiteColor;
    self.titleLabel.font = [UIFont boldSystemFontOfSize:18];
    self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    [self.headerView addSubview:self.titleLabel];

//    self.shareButton = [UIButton buttonWithType:UIButtonTypeSystem];
//    [self.shareButton setTitle:@"Share to Email" forState:UIControlStateNormal];
//    [self.shareButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
//    self.shareButton.layer.borderColor = UIColor.whiteColor.CGColor;
//    self.shareButton.layer.borderWidth = 0.5;
//    self.shareButton.layer.cornerRadius = 14;
//    [self.shareButton addTarget:self
//                        action:@selector(onShare)
//              forControlEvents:UIControlEventTouchUpInside];
//    self.shareButton.titleLabel.font = [UIFont systemFontOfSize:14];
//    self.shareButton.translatesAutoresizingMaskIntoConstraints = NO;
//    [self.headerView addSubview:self.shareButton];

    [NSLayoutConstraint activateConstraints:@[
        [self.headerView.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor],
        [self.headerView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.headerView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.headerView.heightAnchor constraintEqualToConstant:48],

        [self.backButton.leadingAnchor constraintEqualToAnchor:self.headerView.leadingAnchor constant:8],
        [self.backButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
        [self.backButton.widthAnchor constraintEqualToConstant:32],
        [self.backButton.heightAnchor constraintEqualToConstant:32],

        [self.titleLabel.centerXAnchor constraintEqualToAnchor:self.headerView.centerXAnchor],
        [self.titleLabel.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],

//        [self.shareButton.trailingAnchor constraintEqualToAnchor:self.headerView.trailingAnchor constant:-8],
//        [self.shareButton.centerYAnchor constraintEqualToAnchor:self.headerView.centerYAnchor],
//        [self.shareButton.heightAnchor constraintEqualToConstant:28],
//        [self.shareButton.widthAnchor constraintEqualToConstant:120],
    ]];
}

#pragma mark - Setup Offline Banner
//- (void)setupOfflineBanner {
//    self.offlineBanner = [[UIView alloc] init];
//    self.offlineBanner.backgroundColor = [UIColor colorWithRed:1.0 green:0.9 blue:0.6 alpha:1.0];
//    self.offlineBanner.translatesAutoresizingMaskIntoConstraints = NO;
//    self.offlineBanner.hidden = YES;
//
//    UILabel *label = [[UILabel alloc] init];
//    label.text = @"Offline Mode";
//    label.font = [UIFont boldSystemFontOfSize:14];
//    label.translatesAutoresizingMaskIntoConstraints = NO;
//
//    [self.offlineBanner addSubview:label];
//    [self.view addSubview:self.offlineBanner];
//
//    [NSLayoutConstraint activateConstraints:@[
//        [self.offlineBanner.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor],
//        [self.offlineBanner.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
//        [self.offlineBanner.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
//        [self.offlineBanner.heightAnchor constraintEqualToConstant:36],
//
//        [label.centerXAnchor constraintEqualToAnchor:self.offlineBanner.centerXAnchor],
//        [label.centerYAnchor constraintEqualToAnchor:self.offlineBanner.centerYAnchor],
//    ]];
//}

#pragma mark - Setup Tabbar
- (void)setupTabBar {
    self.tabBarView = [[UIView alloc] init];
    self.tabBarView.backgroundColor = self.headerView.backgroundColor;
    self.tabBarView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.tabBarView];

    self.allTabButton = [self createTabButton:@"All" tag:0];
    self.successTabButton = [self createTabButton:@"Success" tag:1];
    self.failedTabButton = [self createTabButton:@"Failed" tag:2];

    UIStackView *stack = [[UIStackView alloc] initWithArrangedSubviews:@[
        self.allTabButton,
        self.successTabButton,
        self.failedTabButton
    ]];
    stack.axis = UILayoutConstraintAxisHorizontal;
    stack.distribution = UIStackViewDistributionFillEqually;
    stack.translatesAutoresizingMaskIntoConstraints = NO;

    [self.tabBarView addSubview:stack];

    [NSLayoutConstraint activateConstraints:@[
        [self.tabBarView.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor],
        [self.tabBarView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.tabBarView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.tabBarView.heightAnchor constraintEqualToConstant:50],

        [stack.topAnchor constraintEqualToAnchor:self.tabBarView.topAnchor],
        [stack.bottomAnchor constraintEqualToAnchor:self.tabBarView.bottomAnchor],
        [stack.leadingAnchor constraintEqualToAnchor:self.tabBarView.leadingAnchor],
        [stack.trailingAnchor constraintEqualToAnchor:self.tabBarView.trailingAnchor],
    ]];
}

- (UIButton *)createTabButton:(NSString *)title tag:(NSInteger)tag {
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
    btn.tag = tag;
    btn.titleLabel.font = [UIFont systemFontOfSize:16];
    [btn setTitle:title forState:UIControlStateNormal];
    [btn setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(onTabPressed:) forControlEvents:UIControlEventTouchUpInside];
    return btn;
}

#pragma mark - Setup TableView
- (void)setupTableView {
    self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.backgroundColor = [UIColor colorWithWhite:0.95 alpha:1.0];
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
    self.tableView.estimatedRowHeight = 120;
    self.tableView.rowHeight = UITableViewAutomaticDimension;

    [self.view addSubview:self.tableView];

    [NSLayoutConstraint activateConstraints:@[
        [self.tableView.topAnchor constraintEqualToAnchor:self.tabBarView.bottomAnchor constant:30],
        [self.tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.tableView.bottomAnchor constraintEqualToAnchor:self.syncAgainButton.topAnchor constant:15],
    ]];
}

#pragma mark - Progress Overlay
- (void)showProgressOverlay {
    if (self.progressOverlay) return;

    self.progressOverlay =
        [[SyncProgressOverlay alloc] initWithFrame:self.view.bounds];

    [self.view addSubview:self.progressOverlay];
}

#pragma mark - Data
- (void)loadHistoryData {
    NSArray *sections = [[OfflineSyncManager shared] historyItemsForUI];
    [self dumpHistoryToFile:sections];

    NSMutableArray *items = [NSMutableArray array];

    for (NSDictionary *section in sections) {
        // Check if the section has "items" key or is itself an item
        NSArray *rows = section[@"items"];
        if (!rows) rows = @[section]; // <-- fallback

        for (NSDictionary *row in rows) {
            HistorySyncItem *item = [HistorySyncItem new];
            item.unitName   = row[@"unitName"];
            item.createdBy  = row[@"createdBy"];
            item.createdOn  = row[@"createdOn"];
            item.uploadedOn = row[@"uploadedOn"];
            item.actionMade = row[@"type"];

            NSString *status = row[@"status"];
            item.status = [status isEqualToString:@"FAILED"]
                          ? HistorySyncStatusFailed
                          : HistorySyncStatusSuccess;

            item.raw = row;
            [items addObject:item];
        }
    }

    self.allItems = items;
    [self updateSyncAgainButtonState];
}

// Dummy data
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.filteredItems.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *cellId = @"HistorySyncCell";

    HistorySyncCell *cell =
        [tableView dequeueReusableCellWithIdentifier:cellId];

    if (!cell) {
        cell = [[HistorySyncCell alloc] initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:cellId];
    }

    HistorySyncItem *item = self.filteredItems[indexPath.row];
    [cell configureWithItem:item];

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [tableView deselectRowAtIndexPath:indexPath animated:YES];

    HistorySyncItem *selectedItem = self.filteredItems[indexPath.row];

    NSDictionary *safeData = [self normalizedRow:selectedItem.raw];
    if (!safeData) {
        NSLog(@"❌ Invalid history item tapped: %@", selectedItem.raw);
        return;
    }

    HistoryDetailsViewController *vc = [HistoryDetailsViewController new];
    vc.itemData = safeData;
    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentViewController:vc animated:YES completion:nil];
}

- (void)setupEmptyState {
    self.emptyStateView = [[UIView alloc] init];
    self.emptyStateView.translatesAutoresizingMaskIntoConstraints = NO;
    self.emptyStateView.hidden = YES;

    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"zerostate_nodata"]];
    imageView.translatesAutoresizingMaskIntoConstraints = NO;

    UILabel *label = [[UILabel alloc] init];
    label.text = @"No history available";
    label.textColor = UIColor.grayColor;
    label.translatesAutoresizingMaskIntoConstraints = NO;

    [self.emptyStateView addSubview:imageView];
    [self.emptyStateView addSubview:label];
    [self.view addSubview:self.emptyStateView];

    [NSLayoutConstraint activateConstraints:@[
        [self.emptyStateView.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
        [self.emptyStateView.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor],

        [imageView.centerXAnchor constraintEqualToAnchor:self.emptyStateView.centerXAnchor],
        [imageView.topAnchor constraintEqualToAnchor:self.emptyStateView.topAnchor],

        [label.topAnchor constraintEqualToAnchor:imageView.bottomAnchor constant:12],
        [label.centerXAnchor constraintEqualToAnchor:self.emptyStateView.centerXAnchor],
    ]];
}

#pragma mark - Footer Button
- (void)setupBottomButton {
    self.syncAgainButton = [UIButton buttonWithType:UIButtonTypeSystem];
    self.syncAgainButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.syncAgainButton.backgroundColor = UIColor.lightGrayColor;
    [self.syncAgainButton setTitle:@"SYNC AGAIN" forState:UIControlStateNormal];
    [self.syncAgainButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
    self.syncAgainButton.enabled = NO;
  
    [self.syncAgainButton addTarget:self
                        action:@selector(onSyncAgain)
              forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:self.syncAgainButton];

    [NSLayoutConstraint activateConstraints:@[
        [self.syncAgainButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.syncAgainButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.syncAgainButton.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
        [self.syncAgainButton.heightAnchor constraintEqualToConstant:45],
    ]];
}

#pragma mark - Helpers
- (void)onBack {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)onTabPressed:(UIButton *)sender {
    self.selectedTab = sender.tag;
    [self applyFilter];
    [self updateTabUI];
}

- (void)updateTabUI {
    NSArray *buttons = @[self.allTabButton, self.successTabButton, self.failedTabButton];
    for (UIButton *btn in buttons) {
        btn.alpha = (btn.tag == self.selectedTab) ? 1.0 : 0.6;
    }
}

- (void)onShare {
    UIAlertController *alert =
        [UIAlertController alertControllerWithTitle:@"Share Pending Items"
                                            message:@"Send pending items to email?"
                                     preferredStyle:UIAlertControllerStyleActionSheet];

    [alert addAction:[UIAlertAction actionWithTitle:@"Send"
                                              style:UIAlertActionStyleDefault
                                            handler:^(UIAlertAction * _Nonnull action) {
        NSLog(@"Share triggered (stub)");
    }]];

    [alert addAction:[UIAlertAction actionWithTitle:@"Cancel"
                                              style:UIAlertActionStyleCancel
                                            handler:nil]];

    [self presentViewController:alert animated:YES completion:nil];
}

- (void)loadMockData {
    HistorySyncItem *a = [HistorySyncItem new];
    a.unitName = @"Unit A-01";
    a.createdBy = @"John";
    a.createdOn = @"12 Aug 2025";
    a.uploadedOn = @"14 Aug 2025";
    a.actionMade = @"Add Issue";
    a.status = HistorySyncStatusSuccess;

    HistorySyncItem *b = [HistorySyncItem new];
    b.unitName = @"Unit B-02";
    b.createdBy = @"Jane";
    b.createdOn = @"10 Aug 2025";
    b.uploadedOn = @"-";
    b.actionMade = @"Add Appoinment";
    b.status = HistorySyncStatusFailed;

    self.allItems = @[a, b];
}

- (void)applyFilter {
    if (self.selectedTab == 0) {
        self.filteredItems = self.allItems;
    } else {
        HistorySyncStatus status =
            (self.selectedTab == 1)
            ? HistorySyncStatusSuccess
            : HistorySyncStatusFailed;

        NSPredicate *predicate =
        [NSPredicate predicateWithBlock:^BOOL(HistorySyncItem *item, NSDictionary *_) {
            return item.status == status;
        }];

        self.filteredItems = [self.allItems filteredArrayUsingPredicate:predicate];
    }

    self.emptyStateView.hidden = (self.filteredItems.count > 0);
    [self.tableView reloadData];
    [self updateSyncAgainButtonState];
}

- (void)onSyncAgain {

    BOOL hasRetryItems = NO;

    for (HistorySyncItem *item in self.allItems) {
        if (item.status == HistorySyncStatusFailed) {
            [[OfflineSyncManager shared] retryHistoryItem:item.raw];
            hasRetryItems = YES;
        }
    }

    if (!hasRetryItems) {
        NSLog(@"No failed items to retry");
        return;
    }

    NSLog(@"🔁 Starting sync again");
  
    [self showProgressOverlay];
    [[OfflineSyncManager shared]
     processNextItemWithProgress:^(NSInteger step,
                                   NSInteger total,
                                   NSString *title) {

         NSLog(@"🔄 Retry %ld / %ld – %@", (long)step, (long)total, title);
      [self.progressOverlay updateStep:step
                                 total:total
                                 title:@"Retrying History Items"];

     } completion:^(BOOL finished) {

         NSLog(@"✅ Retry sync completed");

       dispatch_async(dispatch_get_main_queue(), ^{
             [self.progressOverlay removeFromSuperview];
             self.progressOverlay = nil;

             [self loadHistoryData];
             [self applyFilter];
         });
     }];
}

- (void)dumpHistoryToFile:(id)history {
    NSString *docDir =
        NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                            NSUserDomainMask,
                                            YES).firstObject;

    NSString *path =
        [docDir stringByAppendingPathComponent:@"sync_history_dump.txt"];

    NSString *content =
        [NSString stringWithFormat:@"=== SYNC HISTORY DUMP ===\n%@\n",
         history];

    NSError *error = nil;
    BOOL success =
        [content writeToFile:path
                  atomically:YES
                    encoding:NSUTF8StringEncoding
                       error:&error];

    if (success) {
        NSLog(@"📄 History dumped to: %@", path);
    } else {
        NSLog(@"❌ Failed to dump history: %@", error);
    }
}

- (void)updateSyncAgainButtonState {
    BOOL hasFailedItems = NO;

    for (HistorySyncItem *item in self.allItems) {
        if (item.status == HistorySyncStatusFailed) {
            hasFailedItems = YES;
            break;
        }
    }

    self.syncAgainButton.enabled = hasFailedItems;
    self.syncAgainButton.backgroundColor =
        hasFailedItems ? [UIColor systemBlueColor] : [UIColor lightGrayColor];
}

- (NSDictionary *)normalizedRow:(id)row {
    if ([row isKindOfClass:[NSDictionary class]]) {
        return row;
    }

    if ([row isKindOfClass:[NSString class]]) {
        NSData *data = [(NSString *)row dataUsingEncoding:NSUTF8StringEncoding];
        if (!data) return nil;

        id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        if ([json isKindOfClass:[NSDictionary class]]) {
            return json;
        }
    }

    return nil;
}


@end
