// SyncProjectViewController.mm
#import "SyncProjectViewController.h"
#import "LocalStorage.h"
#import "APIClient.h"
#import "NetworkManager.h"
#import "OfflineSyncManager.h"

typedef NS_ENUM(NSInteger, SyncProjectScreenState) {
    SyncProjectScreenStateOfflineUnit,
    SyncProjectScreenStateSelectProject,
    SyncProjectScreenStateSelectUnit
};

static NSString * const kSyncSelectedUnitsKey = @"SYNC_SELECTEDUNITS";
static NSString * const kProjectListKey = @"PROJECT_LIST";

@interface SyncUnit : NSObject <NSSecureCoding>
@property (nonatomic, strong) NSString *planId;
@property (nonatomic, strong) NSString *displayName;
@property (nonatomic, strong) NSDictionary *project;
@property (nonatomic, strong) NSString *projectId;
@property (nonatomic, strong) NSString *projectName;
@property (nonatomic, assign) BOOL selected;
@end

@implementation SyncUnit

+ (BOOL)supportsSecureCoding {
    return YES;
}

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.planId forKey:@"planId"];
    [coder encodeObject:self.displayName forKey:@"displayName"];
    [coder encodeObject:self.project forKey:@"project"];
    [coder encodeObject:self.projectId forKey:@"projectId"];
    [coder encodeObject:self.projectName forKey:@"projectName"];
    [coder encodeBool:self.selected forKey:@"selected"];
}

- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        _planId = [coder decodeObjectOfClass:[NSString class] forKey:@"planId"];
        _displayName = [coder decodeObjectOfClass:[NSString class] forKey:@"displayName"];
        _project = [coder decodeObjectOfClass:[NSDictionary class] forKey:@"project"];
        _projectId = [coder decodeObjectOfClass:[NSString class] forKey:@"projectId"];
        _projectName = [coder decodeObjectOfClass:[NSString class] forKey:@"projectName"];
        _selected = [coder decodeBoolForKey:@"selected"];
    }
    return self;
}

@end

@interface SyncProject : NSObject
@property (nonatomic, strong) NSString *projectId;
@property (nonatomic, strong) NSString *projectName;
@property (nonatomic, strong) NSArray<SyncUnit *> *units;
@end

@implementation SyncProject
@end

@interface SyncProjectViewController ()
<
UITableViewDelegate,
UITableViewDataSource,
UICollectionViewDelegate,
UICollectionViewDataSource
>

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

// Content containers
@property (nonatomic, strong) UIView *offlineUnitView;
@property (nonatomic, strong) UIView *selectProjectView;
@property (nonatomic, strong) UIView *selectUnitView;

// Common UI
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIActivityIndicatorView *loadingView;

// State
@property (nonatomic, assign) NSInteger selectedUnitCount;

@property (nonatomic, assign) SyncProjectScreenState screenState;
@property (nonatomic, assign) BOOL hasChanges;
@property (nonatomic, strong) NSMutableArray<SyncUnit *> *selectedUnits;

@property (nonatomic, strong) UITableView *offlineTableView;
@property (nonatomic, strong) UITableView *unitTableView;
@property (nonatomic, strong) UICollectionView *projectCollectionView;

@property (nonatomic, strong) NSMutableArray<SyncProject *> *projects;
@property (nonatomic, assign) BOOL isLoadingProjects;
@property (nonatomic, strong) SyncProject *currentProject;

@end


@implementation SyncProjectViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor colorWithWhite:0.96 alpha:1.0];

    self.projects = [NSMutableArray array];
    self.selectedUnits = [NSMutableArray array];
  
    self.loadingView =
        [[UIActivityIndicatorView alloc]
         initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
    self.loadingView.center = self.view.center;
    self.loadingView.hidesWhenStopped = YES;
    [self.view addSubview:self.loadingView];


    [self loadSelectedUnits];
    [self loadProjectList];
    
    [self setupHeader];
    [self setupContentContainers];
    [self setupOfflineUnitView];
    [self setupSelectProjectView];
    [self setupSelectUnitView];

    [self setScreenState:SyncProjectScreenStateOfflineUnit];
}

#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 addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
    self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.backButton.tintColor = UIColor.whiteColor;
    [self.headerView addSubview:self.backButton];
    self.titleLabel = [[UILabel alloc] init];
    self.titleLabel.text = @"Offline Unit";
    self.titleLabel.textColor = UIColor.whiteColor;
    self.titleLabel.font = [UIFont boldSystemFontOfSize:18];
    self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    [self.headerView addSubview:self.titleLabel];
    
    // Constraints
    [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],
    ]];
}

- (void)setHeaderTitle:(NSString *)title {
    self.titleLabel.text = title;
}

#pragma mark - Setup ContentContainer
- (void)setupContentContainers {
    self.offlineUnitView = [UIView new];
    self.selectProjectView = [UIView new];
    self.selectUnitView = [UIView new];

    NSArray *views = @[self.offlineUnitView, self.selectProjectView, self.selectUnitView];

    for (UIView *v in views) {
        v.translatesAutoresizingMaskIntoConstraints = NO;
        v.hidden = YES;
        [self.view addSubview:v];

        [NSLayoutConstraint activateConstraints:@[
            [v.topAnchor constraintEqualToAnchor:self.headerView.bottomAnchor],
            [v.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
            [v.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
            [v.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
        ]];
    }
}

#pragma mark - Offline Unit View
- (void)setupOfflineUnitView {

    UILabel *countLabel = [UILabel new];
    countLabel.font = [UIFont boldSystemFontOfSize:24];
    countLabel.text = @"NO UNITS SELECTED";
    countLabel.translatesAutoresizingMaskIntoConstraints = NO;

    UIButton *addButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [addButton setImage:[UIImage systemImageNamed:@"plus.circle.fill"]
               forState:UIControlStateNormal];
    addButton.tintColor = [UIColor systemTealColor];
    addButton.translatesAutoresizingMaskIntoConstraints = NO;
    [addButton addTarget:self
                  action:@selector(onAddUnit)
        forControlEvents:UIControlEventTouchUpInside];

    UILabel *infoLabel = [UILabel new];
    infoLabel.text = @"Maximum 10 units";
    infoLabel.font = [UIFont systemFontOfSize:16];
    infoLabel.translatesAutoresizingMaskIntoConstraints = NO;

    self.offlineTableView =
        [[UITableView alloc] initWithFrame:CGRectZero
                                     style:UITableViewStyleGrouped];
    self.offlineTableView.translatesAutoresizingMaskIntoConstraints = NO;
    self.offlineTableView.delegate = self;
    self.offlineTableView.dataSource = self;
    self.offlineTableView.allowsSelection = NO;
    [self.offlineTableView registerClass:UITableViewCell.class
                  forCellReuseIdentifier:@"OfflineUnitCell"];


    [self.offlineUnitView addSubview:countLabel];
    [self.offlineUnitView addSubview:addButton];
    [self.offlineUnitView addSubview:infoLabel];
    [self.offlineUnitView addSubview:self.offlineTableView];

    [NSLayoutConstraint activateConstraints:@[
        [countLabel.topAnchor constraintEqualToAnchor:self.offlineUnitView.topAnchor constant:16],
        [countLabel.leadingAnchor constraintEqualToAnchor:self.offlineUnitView.leadingAnchor constant:16],

        [addButton.trailingAnchor constraintEqualToAnchor:self.offlineUnitView.trailingAnchor constant:-16],
        [addButton.centerYAnchor constraintEqualToAnchor:countLabel.centerYAnchor],
        [addButton.widthAnchor constraintEqualToConstant:36],
        [addButton.heightAnchor constraintEqualToConstant:36],

        [infoLabel.topAnchor constraintEqualToAnchor:countLabel.bottomAnchor constant:12],
        [infoLabel.leadingAnchor constraintEqualToAnchor:countLabel.leadingAnchor],

        [self.offlineTableView.topAnchor constraintEqualToAnchor:infoLabel.bottomAnchor constant:12],
       [self.offlineTableView.leadingAnchor constraintEqualToAnchor:self.offlineUnitView.leadingAnchor],
       [self.offlineTableView.trailingAnchor constraintEqualToAnchor:self.offlineUnitView.trailingAnchor],
       [self.offlineTableView.bottomAnchor constraintEqualToAnchor:self.offlineUnitView.bottomAnchor],
    ]];
}

#pragma mark - Select Project View
- (void)setupSelectProjectView {

    UILabel *countLabel = [UILabel new];
    countLabel.font = [UIFont boldSystemFontOfSize:24];
    countLabel.translatesAutoresizingMaskIntoConstraints = NO;

    UILabel *instructionLabel = [UILabel new];
    instructionLabel.text = @"Please select project";
    instructionLabel.font = [UIFont systemFontOfSize:18];
    instructionLabel.translatesAutoresizingMaskIntoConstraints = NO;

    UISearchBar *searchBar = [UISearchBar new];
    searchBar.translatesAutoresizingMaskIntoConstraints = NO;

    UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
    layout.itemSize = CGSizeMake(self.view.bounds.size.width - 32, 120);
    layout.minimumLineSpacing = 12;

    self.projectCollectionView =
        [[UICollectionView alloc] initWithFrame:CGRectZero
                           collectionViewLayout:layout];
    self.projectCollectionView.translatesAutoresizingMaskIntoConstraints = NO;
    self.projectCollectionView.backgroundColor = UIColor.clearColor;
    self.projectCollectionView.delegate = self;
    self.projectCollectionView.dataSource = self;
    [self.projectCollectionView registerClass:UICollectionViewCell.class
                   forCellWithReuseIdentifier:@"ProjectCell"];

    [self.selectProjectView addSubview:countLabel];
    [self.selectProjectView addSubview:instructionLabel];
    [self.selectProjectView addSubview:searchBar];
    [self.selectProjectView addSubview:self.projectCollectionView];

    [NSLayoutConstraint activateConstraints:@[
        [countLabel.topAnchor constraintEqualToAnchor:self.selectProjectView.topAnchor constant:16],
        [countLabel.leadingAnchor constraintEqualToAnchor:self.selectProjectView.leadingAnchor constant:16],

        [instructionLabel.topAnchor constraintEqualToAnchor:countLabel.bottomAnchor constant:8],
        [instructionLabel.leadingAnchor constraintEqualToAnchor:countLabel.leadingAnchor],

        [searchBar.topAnchor constraintEqualToAnchor:instructionLabel.bottomAnchor constant:8],
        [searchBar.leadingAnchor constraintEqualToAnchor:self.selectProjectView.leadingAnchor],
        [searchBar.trailingAnchor constraintEqualToAnchor:self.selectProjectView.trailingAnchor],

        [self.projectCollectionView.topAnchor constraintEqualToAnchor:searchBar.bottomAnchor constant:8],
        [self.projectCollectionView.leadingAnchor constraintEqualToAnchor:self.selectProjectView.leadingAnchor],
        [self.projectCollectionView.trailingAnchor constraintEqualToAnchor:self.selectProjectView.trailingAnchor],
        [self.projectCollectionView.bottomAnchor constraintEqualToAnchor:self.selectProjectView.bottomAnchor],
    ]];
}

#pragma mark - Select Unit View
- (void)setupSelectUnitView {

    UILabel *countLabel = [UILabel new];
    countLabel.font = [UIFont boldSystemFontOfSize:24];
    countLabel.translatesAutoresizingMaskIntoConstraints = NO;

    UILabel *instructionLabel = [UILabel new];
    instructionLabel.text = @"Please select a unit";
    instructionLabel.translatesAutoresizingMaskIntoConstraints = NO;

    UISearchBar *searchBar = [UISearchBar new];
    searchBar.translatesAutoresizingMaskIntoConstraints = NO;

    self.unitTableView = [[UITableView alloc] init];
    self.unitTableView.translatesAutoresizingMaskIntoConstraints = NO;
    self.unitTableView.delegate = self;
    self.unitTableView.dataSource = self;
    [self.unitTableView registerClass:UITableViewCell.class
               forCellReuseIdentifier:@"UnitCell"];

    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [doneButton setTitle:@"DONE" forState:UIControlStateNormal];
    doneButton.backgroundColor = [UIColor systemTealColor];
    doneButton.tintColor = UIColor.whiteColor;
    doneButton.layer.cornerRadius = 8;
    doneButton.translatesAutoresizingMaskIntoConstraints = NO;
    [doneButton addTarget:self
                   action:@selector(onDone)
         forControlEvents:UIControlEventTouchUpInside];

    [self.selectUnitView addSubview:countLabel];
    [self.selectUnitView addSubview:instructionLabel];
    [self.selectUnitView addSubview:searchBar];
    [self.selectUnitView addSubview:self.unitTableView];
    [self.selectUnitView addSubview:doneButton];

    [NSLayoutConstraint activateConstraints:@[
        [countLabel.topAnchor constraintEqualToAnchor:self.selectUnitView.topAnchor constant:16],
        [countLabel.leadingAnchor constraintEqualToAnchor:self.selectUnitView.leadingAnchor constant:16],

        [instructionLabel.topAnchor constraintEqualToAnchor:countLabel.bottomAnchor constant:8],
        [instructionLabel.leadingAnchor constraintEqualToAnchor:countLabel.leadingAnchor],

        [searchBar.topAnchor constraintEqualToAnchor:instructionLabel.bottomAnchor constant:8],
        [searchBar.leadingAnchor constraintEqualToAnchor:self.selectUnitView.leadingAnchor],
        [searchBar.trailingAnchor constraintEqualToAnchor:self.selectUnitView.trailingAnchor],

        [self.unitTableView.topAnchor constraintEqualToAnchor:searchBar.bottomAnchor constant:8],
        [self.unitTableView.leadingAnchor constraintEqualToAnchor:self.selectUnitView.leadingAnchor],
        [self.unitTableView.trailingAnchor constraintEqualToAnchor:self.selectUnitView.trailingAnchor],

        [doneButton.topAnchor constraintEqualToAnchor:self.unitTableView.bottomAnchor constant:12],
        [doneButton.leadingAnchor constraintEqualToAnchor:self.selectUnitView.leadingAnchor constant:16],
        [doneButton.trailingAnchor constraintEqualToAnchor:self.selectUnitView.trailingAnchor constant:-16],
        [doneButton.heightAnchor constraintEqualToConstant:48],
        [doneButton.bottomAnchor constraintEqualToAnchor:self.selectUnitView.bottomAnchor constant:-16],
    ]];
}

#pragma mark - UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    if (tableView == self.offlineTableView) {
        return self.selectedUnits.count;
    }

    if (tableView == self.unitTableView) {
        NSLog(@"Units count = %lu", (unsigned long)self.currentProject.units.count);
        return self.currentProject.units.count;
    }
    return 0;
}

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

    UITableViewCell *cell;

    if (tableView == self.offlineTableView) {

        cell = [tableView dequeueReusableCellWithIdentifier:@"OfflineUnitCell"
                                               forIndexPath:indexPath];

        SyncUnit *unit = self.selectedUnits[indexPath.row];
        cell.textLabel.text = unit.displayName;
        cell.accessoryType = UITableViewCellAccessoryNone;

        // Remove old button (important for reuse)
        UIButton *oldButton = [cell.contentView viewWithTag:999];
        [oldButton removeFromSuperview];

        UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeSystem];
        deleteButton.tag = 999;
        deleteButton.translatesAutoresizingMaskIntoConstraints = NO;
        deleteButton.tintColor = UIColor.systemRedColor;
        [deleteButton setImage:[UIImage systemImageNamed:@"trash"]
                      forState:UIControlStateNormal];

        deleteButton.tag = indexPath.row;
        [deleteButton addTarget:self
                         action:@selector(onDeleteUnit:)
               forControlEvents:UIControlEventTouchUpInside];

        [cell.contentView addSubview:deleteButton];

        [NSLayoutConstraint activateConstraints:@[
            [deleteButton.trailingAnchor constraintEqualToAnchor:cell.contentView.trailingAnchor constant:-16],
            [deleteButton.centerYAnchor constraintEqualToAnchor:cell.contentView.centerYAnchor],
            [deleteButton.widthAnchor constraintEqualToConstant:32],
            [deleteButton.heightAnchor constraintEqualToConstant:32],
        ]];

        return cell;
      
    } else {
        cell = [tableView dequeueReusableCellWithIdentifier:@"UnitCell"
                                               forIndexPath:indexPath];
    }

    SyncUnit *unit;

    if (tableView == self.offlineTableView) {
        unit = self.selectedUnits[indexPath.row];
    } else {
        unit = self.currentProject.units[indexPath.row];
    }

    cell.textLabel.text = unit.displayName;
    cell.accessoryType = unit.selected
        ? UITableViewCellAccessoryCheckmark
        : UITableViewCellAccessoryNone;

    return cell;
}

#pragma mark - UITableViewDelegate

- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
  
  SyncUnit *unit;
  if (tableView == self.offlineTableView) {
    return;
  } else {
    unit = self.currentProject.units[indexPath.row];
  }
  
  [self toggleUnit:unit];
  
  [tableView reloadRowsAtIndexPaths:@[indexPath]
                   withRowAnimation:UITableViewRowAnimationNone];
}

#pragma mark - UICollectionViewDataSource

- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section {
    return self.projects.count;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                           cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    UICollectionViewCell *cell =
        [collectionView dequeueReusableCellWithReuseIdentifier:@"ProjectCell"
                                                  forIndexPath:indexPath];

    cell.contentView.backgroundColor = UIColor.systemGray6Color;
    cell.layer.cornerRadius = 12;

    UILabel *label = [cell.contentView viewWithTag:100];
    if (!label) {
        label = [[UILabel alloc] initWithFrame:cell.contentView.bounds];
        label.tag = 100;
        label.font = [UIFont boldSystemFontOfSize:16];
        label.textAlignment = NSTextAlignmentCenter;
        [cell.contentView addSubview:label];
    }

    SyncProject *project = self.projects[indexPath.item];
    label.text = project.projectName;

    return cell;
}

#pragma mark - UICollectionViewDelegate

- (void)collectionView:(UICollectionView *)collectionView
didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

    self.currentProject = self.projects[indexPath.item];
    [self showSelectUnit];
}

#pragma mark - Project Data
- (void)loadProjectList {

    NSArray *storedProjects =
        [LocalStorage loadArrayForKey:kProjectListKey];

    if (storedProjects && storedProjects.count > 0) {
        NSLog(@"📦 Loaded PROJECT_LIST from storage");

        [self parseAndApplyProjects:storedProjects];
        return;
    }

    NSLog(@"🌐 No cached PROJECT_LIST, requesting from API");
    [self requestProjectList];
}

- (void)requestProjectList {

    [self showLoading:YES];

    [APIClient requestProjectList:^(BOOL success, NSDictionary *data, NSError *error) {
      
        // debug
        NSString *plainText = [NSString stringWithFormat:@"%@", data];
        NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
        NSString *filePath = [docsPath stringByAppendingPathComponent:@"projectList.txt"];
        [plainText writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
        NSLog(@"📁 projectList saved as plain text to: %@", filePath);

        [self showLoading:NO];

        if (error || !data) {
            NSLog(@"❌ Project list API failed: %@", error);
            return;
        }

        // RN parity: status_code check
        if (data[@"status_code"]) {
            NSLog(@"❌ API status error: %@", data[@"message"]);
            return;
        }

        NSDictionary *appData = data[@"AppData"];
        if (![appData[@"status"] isEqualToString:@"success"]) {
            NSLog(@"❌ API failure: %@", appData[@"message"]);
            return;
        }

        NSArray *projects = data[@"Data"];
        if (![projects isKindOfClass:[NSArray class]]) {
            NSLog(@"❌ Invalid project list format");
            return;
        }

        // RN parity: save then reload from storage
        [LocalStorage saveArray:projects forKey:kProjectListKey];

        NSLog(@"✅ PROJECT_LIST saved to storage");

        [self parseAndApplyProjects:projects];
    }];
}

- (void)parseAndApplyProjects:(NSArray *)rawProjects {

    [self.projects removeAllObjects];

    for (NSDictionary *dict in rawProjects) {

        SyncProject *project = [SyncProject new];
        project.projectId = [dict[@"id"] description];
        project.projectName = dict[@"project_name"];

        NSMutableArray *units = [NSMutableArray array];

        for (NSDictionary *unitDict in dict[@"unit"]) {

            SyncUnit *unit = [SyncUnit new];
            unit.planId = [unitDict[@"id"] description];

            NSString *name = unitDict[@"name"];
            if (!name || name.length == 0) {
                NSMutableArray *parts = [NSMutableArray array];
                if (unitDict[@"block"]) [parts addObject:unitDict[@"block"]];
                if (unitDict[@"level"]) [parts addObject:unitDict[@"level"]];
                if (unitDict[@"unit"])  [parts addObject:unitDict[@"unit"]];
                name = [parts componentsJoinedByString:@"-"];
            }

            unit.displayName = name;
            unit.projectId = project.projectId;
            unit.projectName = project.projectName;

            unit.project = @{
                @"id": project.projectId,
                @"project_name": project.projectName
            };

            unit.selected = NO;
            [units addObject:unit];
        }
        project.units = units;
        [self.projects addObject:project];
    }

    // Apply stored selections AFTER parsing
    [self applyStoredSelections];

    // Refresh UI
    [self.projectCollectionView reloadData];
    [self.offlineTableView reloadData];
}

- (void)applyStoredSelections {

    NSArray *stored =
        [LocalStorage loadArrayForKey:kSyncSelectedUnitsKey];
    if (!stored) return;

    for (NSDictionary *dict in stored) {

        NSString *planId = dict[@"plan_id"];
        NSDictionary *project = dict[@"project"];
        NSString *projectId = project[@"id"];

        for (SyncProject *p in self.projects) {
            if (![p.projectId isEqualToString:projectId]) continue;

            for (SyncUnit *u in p.units) {
                if ([u.planId isEqualToString:planId]) {
                    u.selected = YES;
                    if (![self isUnitAlreadySelected:u]) {
                        [self.selectedUnits addObject:u];
                    }
                    break;
                }
            }
        }
    }

    self.selectedUnitCount = self.selectedUnits.count;
}

#pragma mark - Screen State
- (void)setScreenState:(SyncProjectScreenState)state {
    _screenState = state;

    self.offlineUnitView.hidden = YES;
    self.selectProjectView.hidden = YES;
    self.selectUnitView.hidden = YES;

    switch (state) {
        case SyncProjectScreenStateOfflineUnit:
            self.offlineUnitView.hidden = NO;
            [self.offlineTableView reloadData];
            break;

        case SyncProjectScreenStateSelectProject:
            self.selectProjectView.hidden = NO;
            [self.projectCollectionView reloadData];
            break;

        case SyncProjectScreenStateSelectUnit:
            self.selectUnitView.hidden = NO;
            [self.unitTableView reloadData];
            break;
    }
}

#pragma mark - Helpers
- (void)onBack {
    switch (self.screenState) {
        case SyncProjectScreenStateOfflineUnit:
            [self dismissViewControllerAnimated:YES completion:nil];
            break;
        
        case SyncProjectScreenStateSelectProject:
            [self setScreenState:SyncProjectScreenStateOfflineUnit];
            break;

        case SyncProjectScreenStateSelectUnit:
            [self setScreenState:SyncProjectScreenStateSelectProject];
            break;
    }
}

- (void)hideAllContent {
    self.offlineUnitView.hidden = YES;
    self.selectProjectView.hidden = YES;
    self.selectUnitView.hidden = YES;
}

- (void)showOfflineUnit {
    [self setScreenState:SyncProjectScreenStateOfflineUnit];
    [self setHeaderTitle:@"Offline Unit"];
}

- (void)showSelectProject {
    [self hideAllContent];
    [self setHeaderTitle:@"Add Unit"];
    self.selectProjectView.hidden = NO;
}

- (void)showSelectUnit {
    [self setScreenState:SyncProjectScreenStateSelectUnit];
    [self setHeaderTitle:@"Add Unit"];
}

- (void)onAddUnit {
    [self showSelectProject];
}

- (void)onDone {
    NSLog(@"Selected units count: %lu",
          (unsigned long)self.selectedUnits.count);
    NSMutableArray *dictArray = [NSMutableArray array];
    for (SyncUnit *unit in self.selectedUnits) {
        [dictArray addObject:[self dictionaryFromUnit:unit]];
    }
    [self showOfflineUnit];
}

- (BOOL)canAddUnit {
    return self.selectedUnits.count < 10;
}

- (void)toggleUnit:(SyncUnit *)unit {

    if (unit.selected) {
        unit.selected = NO;

        NSPredicate *predicate =
            [NSPredicate predicateWithFormat:@"planId != %@", unit.planId];
        self.selectedUnits =
            [[self.selectedUnits filteredArrayUsingPredicate:predicate] mutableCopy];

    } else {
        if (![self canAddUnit]) {
            NSLog(@"only 10 units recommended");
            return;
        }

        if (![self isUnitAlreadySelected:unit]) {
            unit.selected = YES;
            [self.selectedUnits addObject:unit];
        }
    }

    self.hasChanges = YES;
    self.selectedUnitCount = self.selectedUnits.count;

    [self saveSelectedUnits];
}

- (void)showLoading:(BOOL)show {
    if (show) {
        [self.loadingView startAnimating];
    } else {
        [self.loadingView stopAnimating];
    }
}

- (NSDictionary *)dictionaryFromUnit:(SyncUnit *)unit {
    return @{
        @"plan_id": unit.planId ?: @"",
        @"sort_name": unit.displayName ?: @"",
        @"project": @{
            @"id": unit.projectId ?: @"",
            @"project_name": unit.projectName ?: @""
        }
    };
}

- (SyncUnit *)unitFromDictionary:(NSDictionary *)dict {
    SyncUnit *unit = [SyncUnit new];
    unit.planId = dict[@"plan_id"];
    unit.displayName = dict[@"sort_name"];

    NSDictionary *project = dict[@"project"];
    unit.projectId = project[@"id"];
    unit.projectName = project[@"project_name"];

    unit.selected = YES;
    return unit;
}

- (void)saveSelectedUnits {
    NSMutableArray *array = [NSMutableArray array];

    for (SyncUnit *unit in self.selectedUnits) {
        [array addObject:[self dictionaryFromUnit:unit]];
    }

    [LocalStorage saveArray:array forKey:kSyncSelectedUnitsKey];
}

- (void)loadSelectedUnits {
    NSArray *stored = [LocalStorage loadArrayForKey:kSyncSelectedUnitsKey];
    if (!stored) return;

    [self.selectedUnits removeAllObjects];

    for (NSDictionary *dict in stored) {
        SyncUnit *unit = [self unitFromDictionary:dict];
        if (![self isUnitAlreadySelected:unit]) {
            [self.selectedUnits addObject:unit];
        }
    }

    self.selectedUnitCount = self.selectedUnits.count;
}

- (BOOL)isUnitAlreadySelected:(SyncUnit *)unit {
    for (SyncUnit *u in self.selectedUnits) {
        if ([u.planId isEqualToString:unit.planId]) {
            return YES;
        }
    }
    return NO;
}

- (void)onDeleteUnit:(UIButton *)sender {

    NSInteger index = sender.tag;
    if (index < 0 || index >= self.selectedUnits.count) return;

    SyncUnit *unit = self.selectedUnits[index];

    unit.selected = NO;
    [self.selectedUnits removeObjectAtIndex:index];

    self.selectedUnitCount = self.selectedUnits.count;
    self.hasChanges = YES;

    [self saveSelectedUnits];

    [self.offlineTableView reloadData];
}

@end
