//  AppointmentViewMoreViewController.mm

#import "AppointmentViewMoreViewController.h"
#import "FSCalendar.h"
#import "DashboardAPIClient.h"
#import "AppointmentViewController.h"
#import "AppointmentDetailsViewController.h"

@interface ListingCell : UITableViewCell

@property (nonatomic, strong) UILabel *statusLabel;
@property (nonatomic, strong) UILabel *timeBadge;
@property (nonatomic, strong) UILabel *unitOwnerLabel;

@end

@implementation ListingCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (!self) return nil;

    // Status label (left top)
    self.statusLabel = [[UILabel alloc] init];
    self.statusLabel.font = [UIFont boldSystemFontOfSize:14];
    self.statusLabel.translatesAutoresizingMaskIntoConstraints = NO;
    [self.contentView addSubview:self.statusLabel];

    // Time badge (right top)
    self.timeBadge = [[UILabel alloc] init];
    self.timeBadge.font = [UIFont systemFontOfSize:12 weight:UIFontWeightSemibold];
    self.timeBadge.textAlignment = NSTextAlignmentCenter;
    self.timeBadge.layer.cornerRadius = 12;
    self.timeBadge.layer.masksToBounds = YES;
    self.timeBadge.translatesAutoresizingMaskIntoConstraints = NO;
    [self.contentView addSubview:self.timeBadge];

    // Unit + Owner (full width bottom)
    self.unitOwnerLabel = [[UILabel alloc] init];
    self.unitOwnerLabel.font = [UIFont systemFontOfSize:13];
    self.unitOwnerLabel.textColor = UIColor.darkGrayColor;
    self.unitOwnerLabel.translatesAutoresizingMaskIntoConstraints = NO;
    [self.contentView addSubview:self.unitOwnerLabel];

    // AutoLayout constraints
    [NSLayoutConstraint activateConstraints:@[
        // top row left
        [self.statusLabel.topAnchor constraintEqualToAnchor:self.contentView.topAnchor constant:8],
        [self.statusLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],

        // top row right — time badge
        [self.timeBadge.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-16],
        [self.timeBadge.centerYAnchor constraintEqualToAnchor:self.statusLabel.centerYAnchor],
        [self.timeBadge.widthAnchor constraintEqualToConstant:70],
        [self.timeBadge.heightAnchor constraintEqualToConstant:24],

        // bottom row full width
        [self.unitOwnerLabel.topAnchor constraintEqualToAnchor:self.statusLabel.bottomAnchor constant:6],
        [self.unitOwnerLabel.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:16],
        [self.unitOwnerLabel.trailingAnchor constraintEqualToAnchor:self.timeBadge.trailingAnchor],
        [self.unitOwnerLabel.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor constant:-8]
    ]];

    return self;
}

@end

@interface AppointmentViewMoreViewController () <UITableViewDelegate, UITableViewDataSource, FSCalendarDelegate, FSCalendarDataSource>

@property (nonatomic, strong) UIView *topBar;
@property (nonatomic, strong) UIButton *backButton;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *toggleTabButton;

@property (nonatomic, strong) UIView *filterBar;
@property (nonatomic, strong) UILabel *filterLabel;
@property (nonatomic, strong) UIButton *filterButton;

@property (nonatomic, strong) UIView *calendarContainer;
@property (nonatomic, strong) UIView *listingContainer;
@property (nonatomic, strong) UITableView *listingTable;

@property (nonatomic, strong) UIView *bottomButtonContainer;
@property (nonatomic, strong) UIButton *makeAppointmentButton;

@property (nonatomic, strong) UIView *filterOverlay;

@property (nonatomic, strong) UIActivityIndicatorView *loadingView;

@property (nonatomic, assign) BOOL showingCalendar;

@property (nonatomic, strong) NSArray *arrayAppointmentFull;
@property (nonatomic, strong) NSMutableArray *arrayListing;
@property (nonatomic, strong) NSMutableArray *arrayListingSection;
@property (nonatomic, strong) NSMutableDictionary *aryDotsByDate;

@property (nonatomic, copy) NSString *apptFilterType;
@property (nonatomic, copy) NSString *apptFilterTime;

@property (nonatomic, assign) BOOL blnLoading;
@property (nonatomic, assign) BOOL blnRefreshCalendar;

@property (nonatomic, strong) FSCalendar *calendar;
@property (nonatomic ,strong) NSLayoutConstraint *calendarHeightConstraint;
@property (nonatomic, strong) UIButton *collapseButton;
@property (nonatomic, assign) BOOL calendarCollapsed;
@property (nonatomic, strong) NSArray<NSDictionary *> *agendaSections;
@property (nonatomic, strong) NSDate *selectedAgendaStartDate;
@property (nonatomic, strong) NSDateFormatter *stringDF;

@end

@implementation AppointmentViewMoreViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = UIColor.whiteColor;
  
    self.arrayAppointmentFull = [NSMutableArray array];
    self.arrayListing = [NSMutableArray array];
    self.arrayListingSection = [NSMutableArray array];
    self.aryDotsByDate = [NSMutableDictionary dictionary];

    self.apptFilterType = @"All";
    self.apptFilterTime = @"Upcoming";

    self.showingCalendar = YES;
  
    self.stringDF = [[NSDateFormatter alloc] init];
    self.stringDF.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    self.stringDF.dateFormat = @"dd MMM yyyy";

    [self setupTopBar];
    [self setupFilterBar];
    [self setupBottomButton];
    [self setupCalendarView];
    [self setupListingView];
    [self setupFilterOverlay];
    [self setupLoadingOverlay];
    [self fetchDashboardInfo];
}

#pragma mark - Top Bar
- (void)setupTopBar {
    self.topBar = [[UIView alloc] init];
    self.topBar.backgroundColor = [UIColor colorWithRed:0 green:0.4 blue:0.55 alpha:1];
    self.topBar.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.topBar];

    self.backButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.backButton addTarget:self action:@selector(onBack) forControlEvents:UIControlEventTouchUpInside];
    self.backButton.translatesAutoresizingMaskIntoConstraints = NO;
    [self.backButton setImage:[UIImage systemImageNamed:@"chevron.left"] forState:UIControlStateNormal];
    self.backButton.tintColor = UIColor.whiteColor;
    [self.topBar addSubview:self.backButton];
  
    self.titleLabel = [[UILabel alloc] init];
    self.titleLabel.text = @"Appointment";
    self.titleLabel.textColor = UIColor.whiteColor;
    self.titleLabel.textAlignment = NSTextAlignmentCenter;
    self.titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    [self.topBar addSubview:self.titleLabel];

    self.toggleTabButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.toggleTabButton setImage:[UIImage systemImageNamed:@"list.bullet"] forState:UIControlStateNormal];
    [self.toggleTabButton addTarget:self action:@selector(onToggleTab) forControlEvents:UIControlEventTouchUpInside];
    self.toggleTabButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.toggleTabButton.tintColor = [UIColor whiteColor];
    [self.topBar addSubview:self.toggleTabButton];

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

        [self.backButton.leadingAnchor constraintEqualToAnchor:self.topBar.leadingAnchor constant:12],
        [self.backButton.centerYAnchor constraintEqualToAnchor:self.topBar.centerYAnchor],
        [self.backButton.widthAnchor constraintEqualToConstant:48],
        [self.backButton.heightAnchor constraintEqualToConstant:48],

        [self.toggleTabButton.trailingAnchor constraintEqualToAnchor:self.topBar.trailingAnchor constant:-12],
        [self.toggleTabButton.centerYAnchor constraintEqualToAnchor:self.topBar.centerYAnchor],
        [self.toggleTabButton.widthAnchor constraintEqualToConstant:48],
        [self.toggleTabButton.heightAnchor constraintEqualToConstant:48],

        [self.titleLabel.centerXAnchor constraintEqualToAnchor:self.topBar.centerXAnchor],
        [self.titleLabel.centerYAnchor constraintEqualToAnchor:self.topBar.centerYAnchor]
    ]];
}

#pragma mark - Filter Bar
- (void)setupFilterBar {
    self.filterBar = [[UIView alloc] init];
    self.filterBar.backgroundColor = [UIColor colorWithWhite:0.6 alpha:1];
    self.filterBar.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.filterBar];

    self.filterLabel = [[UILabel alloc] init];
    self.filterLabel.text = @"Filter by All (Upcoming)";
    self.filterLabel.textColor = UIColor.whiteColor;
    self.filterLabel.translatesAutoresizingMaskIntoConstraints = NO;
    [self.filterBar addSubview:self.filterLabel];

    self.filterButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [self.filterButton setImage:[UIImage systemImageNamed:@"slider.horizontal.3"] forState:UIControlStateNormal];
    [self.filterButton addTarget:self action:@selector(onFilterButton) forControlEvents:UIControlEventTouchUpInside];
    self.filterButton.translatesAutoresizingMaskIntoConstraints = NO;
    self.filterButton.tintColor = [UIColor whiteColor];
    [self.filterBar addSubview:self.filterButton];
    self.calendarCollapsed = YES;

    [NSLayoutConstraint activateConstraints:@[
        [self.filterBar.topAnchor constraintEqualToAnchor:self.topBar.bottomAnchor],
        [self.filterBar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.filterBar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.filterBar.heightAnchor constraintEqualToConstant:48],

        [self.filterLabel.leadingAnchor constraintEqualToAnchor:self.filterBar.leadingAnchor constant:16],
        [self.filterLabel.centerYAnchor constraintEqualToAnchor:self.filterBar.centerYAnchor],

        [self.filterButton.trailingAnchor constraintEqualToAnchor:self.filterBar.trailingAnchor constant:-12],
        [self.filterButton.centerYAnchor constraintEqualToAnchor:self.filterBar.centerYAnchor],
        [self.filterButton.widthAnchor constraintEqualToConstant:36],
        [self.filterButton.heightAnchor constraintEqualToConstant:36]
    ]];
}

#pragma mark - Listing Container
- (void)setupListingView {
    // Container for listing
    self.listingContainer = [[UIView alloc] init];
    self.listingContainer.backgroundColor = UIColor.whiteColor;
    self.listingContainer.translatesAutoresizingMaskIntoConstraints = NO;
    self.listingContainer.hidden = YES;
    [self.view addSubview:self.listingContainer];
  
    // Listing table
    self.listingTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
    self.listingTable.delegate = self;
    self.listingTable.dataSource = self;
    self.listingTable.translatesAutoresizingMaskIntoConstraints = NO;
    [self.listingContainer addSubview:self.listingTable];

    // ✅ Register cell class **before any dequeuing**
    [self.listingTable registerClass:[ListingCell class] forCellReuseIdentifier:@"ListingCell"];

    // Container constraints
    [NSLayoutConstraint activateConstraints:@[
        [self.listingContainer.topAnchor constraintEqualToAnchor:self.filterBar.bottomAnchor],
        [self.listingContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.listingContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.listingContainer.bottomAnchor constraintEqualToAnchor:self.bottomButtonContainer.topAnchor]
    ]];

    // Table fills container
    [NSLayoutConstraint activateConstraints:@[
        [self.listingTable.topAnchor constraintEqualToAnchor:self.listingContainer.topAnchor constant:8],
        [self.listingTable.leadingAnchor constraintEqualToAnchor:self.listingContainer.leadingAnchor],
        [self.listingTable.trailingAnchor constraintEqualToAnchor:self.listingContainer.trailingAnchor],
        [self.listingTable.bottomAnchor constraintEqualToAnchor:self.listingContainer.bottomAnchor]
    ]];

    // Ensure automatic row height (optional)
    self.listingTable.estimatedRowHeight = 60;
    self.listingTable.rowHeight = UITableViewAutomaticDimension;
}

#pragma mark - Calendar
- (void)setupCalendarView {
    // --- Calendar Container ---
    self.calendarContainer = [[UIView alloc] init];
    self.calendarContainer.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.calendarContainer];
    self.calendarHeightConstraint =
        [self.calendarContainer.heightAnchor constraintEqualToConstant:300];
    self.calendarHeightConstraint.active = YES;

    [NSLayoutConstraint activateConstraints:@[
        [self.calendarContainer.topAnchor constraintEqualToAnchor:self.filterBar.bottomAnchor constant:8],
        [self.calendarContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.calendarContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
    ]];

    // --- FSCalendar ---
    self.calendar = [[FSCalendar alloc] initWithFrame:CGRectZero];
    self.calendar.translatesAutoresizingMaskIntoConstraints = NO;
    self.calendar.dataSource = self;
    self.calendar.delegate = self;
    self.calendar.scope = FSCalendarScopeWeek;
    [self.calendarContainer addSubview:self.calendar];

    [NSLayoutConstraint activateConstraints:@[
        [self.calendar.topAnchor constraintEqualToAnchor:self.calendarContainer.topAnchor],
        [self.calendar.leadingAnchor constraintEqualToAnchor:self.calendarContainer.leadingAnchor],
        [self.calendar.trailingAnchor constraintEqualToAnchor:self.calendarContainer.trailingAnchor],
        [self.calendar.bottomAnchor constraintEqualToAnchor:self.calendarContainer.bottomAnchor],
    ]];
  
    // --- Collapse / Expand Button ---
    self.collapseButton = [UIButton buttonWithType:UIButtonTypeSystem];
    self.collapseButton.translatesAutoresizingMaskIntoConstraints = NO;
    [self.collapseButton setTitle:@"Expand Calendar ▼" forState:UIControlStateNormal];
    self.collapseButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
    [self.collapseButton addTarget:self
                            action:@selector(onToggleCalendar)
                  forControlEvents:UIControlEventTouchUpInside];

    [self.view addSubview:self.collapseButton];
  
    // --- Button Constraints ---
    [NSLayoutConstraint activateConstraints:@[
        [self.collapseButton.topAnchor constraintEqualToAnchor:self.calendarContainer.bottomAnchor constant:8],
        [self.collapseButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:16],
        [self.collapseButton.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-16],
        [self.collapseButton.heightAnchor constraintEqualToConstant:30],
    ]];
  
    // --- Agenda Table ---
    self.agendaTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
    self.agendaTable.delegate = self;
    self.agendaTable.dataSource = self;
    self.agendaTable.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.agendaTable];

    [self.agendaTable registerClass:[ListingCell class] forCellReuseIdentifier:@"ListingCell"];
    self.agendaTable.estimatedRowHeight = 60;
    self.agendaTable.rowHeight = UITableViewAutomaticDimension;

    // Pull-to-refresh
//    UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
//    [refresh addTarget:self action:@selector(onRefresh) forControlEvents:UIControlEventValueChanged];
//    if (@available(iOS 10.0, *)) {
//        self.agendaTable.refreshControl = refresh;
//    } else {
//        [self.agendaTable addSubview:refresh];
//    }

    [NSLayoutConstraint activateConstraints:@[
        [self.agendaTable.topAnchor constraintEqualToAnchor:self.collapseButton.bottomAnchor constant:8],
        [self.agendaTable.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.agendaTable.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.agendaTable.bottomAnchor constraintEqualToAnchor:self.bottomButtonContainer.topAnchor constant:-8],
    ]];
}

#pragma mark - FSCalendarDelegate
- (void)calendar:(FSCalendar *)calendar didSelectDate:(NSDate *)date atMonthPosition:(FSCalendarMonthPosition)position {

    // Save selected date
    self.selectedAgendaStartDate = [[NSCalendar currentCalendar] startOfDayForDate:date];

    // Rebuild the agenda so that selected date becomes the start
    [self prepareAgendaSections];

    // Scroll to the section for this date
    NSString *selectedDateString = [self.stringDF stringFromDate:self.selectedAgendaStartDate];
    NSInteger sectionIndex = NSNotFound;
    for (NSInteger i = 0; i < self.agendaSections.count; i++) {
        if ([self.agendaSections[i][@"date"] isEqualToString:selectedDateString]) {
            sectionIndex = i;
            break;
        }
    }

    if (sectionIndex != NSNotFound) {
        [self.agendaTable scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:sectionIndex]
                                  atScrollPosition:UITableViewScrollPositionTop
                                          animated:YES];
    }
}

// If your FSCalendar supports eventColorsForDate:
- (NSArray<UIColor *> *)calendar:(FSCalendar *)calendar appearance:(FSCalendarAppearance *)appearance eventColorsForDate:(NSDate *)date {
    NSDateFormatter *dfOut = [[NSDateFormatter alloc] init];
    dfOut.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    dfOut.dateFormat = @"yyyy-MM-dd";
    NSString *key = [dfOut stringFromDate:date];

    NSArray *dots = self.aryDotsByDate[key];
    if (!dots) return nil;
    NSMutableArray *colors = [NSMutableArray array];
    for (NSDictionary *d in dots) {
        UIColor *c = d[@"color"];
        if ([c isKindOfClass:[UIColor class]]) [colors addObject:c];
    }
    return colors;
}

- (NSInteger)calendar:(FSCalendar *)calendar numberOfEventsForDate:(NSDate *)date {
    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    df.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    df.dateFormat = @"yyyy-MM-dd";
    NSString *key = [df stringFromDate:date];

    NSArray *events = self.aryDotsByDate[key];
    return events.count;   // number of dots to show
}

- (void)calendar:(FSCalendar *)calendar boundingRectWillChange:(CGRect)bounds animated:(BOOL)animated {
    self.calendarHeightConstraint.constant = bounds.size.height;
    [self.view layoutIfNeeded];
}

- (void)onToggleCalendar {
    self.calendarCollapsed = !self.calendarCollapsed;

    FSCalendarScope newScope = self.calendarCollapsed ? FSCalendarScopeWeek : FSCalendarScopeMonth;
    [self.calendar setScope:newScope animated:YES];
    
    NSString *title = self.calendarCollapsed ? @"Expand Calendar ▼" : @"Collapse Calendar ▲";
    [self.collapseButton setTitle:title forState:UIControlStateNormal];
}

#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    if (tableView == self.agendaTable) {
      return self.agendaSections.count;
    }
    return self.arrayListingSection.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (tableView == self.agendaTable) {
      NSDictionary *sec = self.agendaSections[section];
      NSArray *items = sec[@"items"];
      return (items.count > 0) ? items.count : 1; // always 1 for empty section
    }
    NSDictionary *sec = self.arrayListingSection[section];
    return [sec[@"data"] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ListingCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ListingCell" forIndexPath:indexPath];

    if (tableView == self.agendaTable) {
        NSDictionary *sec = self.agendaSections[indexPath.section];
        NSArray *items = sec[@"items"];

        if (items.count == 0) {
            // Empty section cell
            cell.statusLabel.text = @"No Appointments";
            cell.timeBadge.text = @"";
            cell.timeBadge.backgroundColor = UIColor.clearColor;
            cell.unitOwnerLabel.text = @"";
        } else {
            NSDictionary *item = items[indexPath.row];
            NSString *status = item[@"status"] ?: @"";
            NSString *apptType = item[@"appointment_type"] ?: @"";
            NSString *startTime = item[@"start_time"] ?: @"";

            cell.statusLabel.text = [status isEqualToString:@"Cancelled"] ? status : apptType;
            cell.timeBadge.text = startTime;
            cell.timeBadge.backgroundColor = [apptType isEqualToString:@"Handover"]
                ? [self colorFromHex:@"#047C74"]
                : [self colorFromHex:@"#C84132"];
            cell.timeBadge.textColor = UIColor.whiteColor;

            NSArray *primary = item[@"primary_buyer"];
            NSArray *joint = item[@"joint_buyer"];
            NSString *owner = (primary.count > 0) ? primary[0][@"name"]
                            : (joint.count > 0 ? joint[0][@"name"] : @"");

            cell.unitOwnerLabel.text = [NSString stringWithFormat:@"%@ (%@)", item[@"unit_no"], owner];
        }
    } else {
        // normal listing table config
        NSDictionary *sec = self.arrayListingSection[indexPath.section];
        NSDictionary *item = sec[@"data"][indexPath.row];

        NSString *status = item[@"status"] ?: @"";
        NSString *apptType = item[@"appointment_type"] ?: @"";
        NSString *startTime = item[@"start_time"] ?: @"";

        cell.statusLabel.text = [status isEqualToString:@"Cancelled"] ? status : apptType;
        cell.timeBadge.text = startTime;
        cell.timeBadge.backgroundColor = [apptType isEqualToString:@"Handover"]
            ? [self colorFromHex:@"#047C74"]
            : [self colorFromHex:@"#C84132"];
        cell.timeBadge.textColor = UIColor.whiteColor;

        NSArray *primary = item[@"primary_buyer"];
        NSArray *joint = item[@"joint_buyer"];
        NSString *owner = (primary.count > 0) ? primary[0][@"name"]
                        : (joint.count > 0 ? joint[0][@"name"] : @"");

        cell.unitOwnerLabel.text = [NSString stringWithFormat:@"%@ (%@)", item[@"unit_no"], owner];
    }
    return cell;
}

#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (tableView == self.agendaTable) {
        NSDictionary *sec = self.agendaSections[indexPath.section];
        NSArray *items = sec[@"items"];
        if (items.count == 0) return 0.1; // empty cell height
        return 60; // normal cell height
    }
    return 60;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    return 30;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
    return 0.1;
}
  
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
  if (tableView == self.agendaTable) {
    NSDictionary *sec = self.agendaSections[section];
    return sec[@"date"];
  }
    return @"1";
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if (tableView == self.agendaTable) {
      NSDictionary *sec = self.agendaSections[section];
       NSString *dateString = sec[@"date"];
       
       UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, tableView.bounds.size.width - 32, 30)];
       lbl.text = dateString;
       lbl.font = [UIFont boldSystemFontOfSize:14];
       lbl.textColor = UIColor.darkGrayColor;
       
       UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 30)];
       v.backgroundColor = UIColor.whiteColor;
       [v addSubview:lbl];
       return v;
    }

    NSDictionary *sec = self.arrayListingSection[section];
    UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, tableView.bounds.size.width - 32, 30)];
    lbl.text = sec[@"title"];
    lbl.font = [UIFont boldSystemFontOfSize:14];
    lbl.textColor = UIColor.darkGrayColor;

    UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 30)];
    [v addSubview:lbl];
    return v;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSDictionary *item;
    if (tableView == self.agendaTable) {
        NSDictionary *sec = self.agendaSections[indexPath.section];
        NSArray *items = sec[@"items"];
        if (items.count == 0) return; // nothing to select
        item = items[indexPath.row];
    } else {
        NSDictionary *sec = self.arrayListingSection[indexPath.section];
        item = sec[@"data"][indexPath.row];
    }
    [self clickListingItemWithItem:item];
}

- (void)clickListingItemWithItem:(NSDictionary *)item {
    AppointmentDetailsViewController *vc = [[AppointmentDetailsViewController alloc] initWithNibName:nil bundle:nil];
    vc.appointmentData = item;
    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentViewController:vc animated:YES completion:nil];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView != self.agendaTable) return;

    // Get visible rows
    NSArray<NSIndexPath *> *visible = [self.agendaTable indexPathsForVisibleRows];
    if (visible.count == 0) return;

    // Find the *topmost* row (smallest section + row)
    NSIndexPath *topIndex = visible.firstObject;
    for (NSIndexPath *ip in visible) {
        if (ip.section < topIndex.section ||
           (ip.section == topIndex.section && ip.row < topIndex.row)) {
            topIndex = ip;
        }
    }

    // Get date from section
    NSDictionary *sectionInfo = self.agendaSections[topIndex.section];
    NSString *dateStr = sectionInfo[@"date"];
    if (!dateStr) return;

    // Convert to NSDate
    NSDate *date = [self.stringDF dateFromString:dateStr];
    if (!date) return;

    // Avoid infinite loop when we update calendar from user taps
    if ([self.calendar.selectedDate isEqualToDate:date]) return;

    // Update calendar selection
    [self.calendar selectDate:date scrollToDate:YES];
}

- (void)prepareAgendaSections {

    if (!self.arrayListing || self.arrayListing.count == 0) {
        // still show at least today
        NSDate *today = [[NSCalendar currentCalendar] startOfDayForDate:[NSDate date]];
        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        df.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
        df.dateFormat = @"dd MMM yyyy";

        NSString *todayStr = [df stringFromDate:today];
        self.agendaSections = @[ @{ @"date": todayStr, @"items": @[] } ];
        [self.agendaTable reloadData];
        return;
    }

    // 1️⃣ Map: date string -> appointments
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    NSDateFormatter *df = [[NSDateFormatter alloc] init];
    df.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    df.dateFormat = @"dd MMM yyyy";

    for (NSDictionary *item in self.arrayListing) {
        NSString *dateStr = item[@"start_date"];
        if (!dateStr) continue;

        if (!dict[dateStr]) dict[dateStr] = [NSMutableArray array];
        [dict[dateStr] addObject:item];
    }

    // 2️⃣ Sort all appointment dates
    NSArray *allDates = [[dict allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString *a, NSString *b) {
        NSDate *da = [df dateFromString:a];
        NSDate *db = [df dateFromString:b];
        return [da compare:db];
    }];

    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSDate *today = [calendar startOfDayForDate:[NSDate date]];

    // If no appointment dates exist (edge case)
    NSDate *firstAppt = (allDates.count > 0) ? [df dateFromString:allDates.firstObject] : today;
    NSDate *lastAppt  = (allDates.count > 0) ? [df dateFromString:allDates.lastObject]  : today;

    // 3️⃣ Expand date range like RN Agenda
    // Start at the earlier of today or first appointment
    NSDate *startDate;

    // If user selected a date, start from there
    if (self.selectedAgendaStartDate) {
        startDate = self.selectedAgendaStartDate;
    } else {
        // default behavior (today or firstAppt)
        startDate = [firstAppt compare:today] == NSOrderedAscending ? firstAppt : today;
    }
  
    // Add a forward buffer (e.g. 60 days)
    NSDate *endDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:60 toDate:lastAppt options:0];

    // 4️⃣ Build all sections
    NSMutableArray *sections = [NSMutableArray array];
    NSDate *currentDate = startDate;

    while ([currentDate compare:endDate] != NSOrderedDescending) {

        NSString *dateStr = [df stringFromDate:currentDate];
        NSArray *itemsForDate = dict[dateStr] ?: @[];

        [sections addObject:@{
            @"date": dateStr,
            @"items": itemsForDate
        }];

        currentDate = [calendar dateByAddingUnit:NSCalendarUnitDay value:1
                                          toDate:currentDate
                                         options:0];
    }

    self.agendaSections = sections;
    [self.agendaTable reloadData];
}

- (void)onRefresh {
    [self fetchDashboardInfo];
}

#pragma mark - Bottom Button
- (void)setupBottomButton {
    self.bottomButtonContainer = [[UIView alloc] init];
    self.bottomButtonContainer.backgroundColor = [UIColor colorWithRed:0 green:0.4 blue:0.55 alpha:1];
    self.bottomButtonContainer.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:self.bottomButtonContainer];
    
    self.makeAppointmentButton = [UIButton buttonWithType:UIButtonTypeSystem];
    [self.makeAppointmentButton setTitle:@"Make Appointment" forState:UIControlStateNormal];
    [self.makeAppointmentButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    self.makeAppointmentButton.translatesAutoresizingMaskIntoConstraints = NO;
    [self.makeAppointmentButton addTarget:self action:@selector(onMakeAppointment) forControlEvents:UIControlEventTouchUpInside];
    [self.bottomButtonContainer addSubview:self.makeAppointmentButton];
    
    [NSLayoutConstraint activateConstraints:@[
        [self.bottomButtonContainer.bottomAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.bottomAnchor],
        [self.bottomButtonContainer.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
        [self.bottomButtonContainer.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor],
        [self.bottomButtonContainer.heightAnchor constraintEqualToConstant:56],
        
        [self.makeAppointmentButton.topAnchor constraintEqualToAnchor:self.bottomButtonContainer.topAnchor],
        [self.makeAppointmentButton.bottomAnchor constraintEqualToAnchor:self.bottomButtonContainer.bottomAnchor],
        [self.makeAppointmentButton.leadingAnchor constraintEqualToAnchor:self.bottomButtonContainer.leadingAnchor],
        [self.makeAppointmentButton.trailingAnchor constraintEqualToAnchor:self.bottomButtonContainer.trailingAnchor]
    ]];
}


#pragma mark - Filter Overlay
- (void)setupFilterOverlay {
    self.filterOverlay = [[UIView alloc] initWithFrame:self.view.bounds];
    self.filterOverlay.hidden = YES;
    self.filterOverlay.userInteractionEnabled = NO;

    // 1️⃣ Dim background
    UIView *dimView = [[UIView alloc] initWithFrame:self.filterOverlay.bounds];
    dimView.backgroundColor = [UIColor whiteColor];
    [self.filterOverlay addSubview:dimView];

    // Tap anywhere to close
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                           action:@selector(hideFilterOverlay)];
    [dimView addGestureRecognizer:tap];

    // 2️⃣ Content container (MUST BE ABOVE dimView)
    UIView *contentView = [[UIView alloc] initWithFrame:self.filterOverlay.bounds];
    contentView.backgroundColor = UIColor.clearColor; // content is transparent
    [self.filterOverlay addSubview:contentView];

    // -----------------------------
    // ADD YOUR FILTER BUTTONS HERE
    // -----------------------------
    CGFloat y = 100;

    // 1️⃣ Appointment Type Header
    [self createFilterHeaderWithText:@"Appointment Type" y:y parent:contentView];
    y += 40;

    // 2️⃣ Type options
    NSArray *typeTitles = @[@"All", @"Handover", @"Joint Inspection", @"Rectification"];
    for (int i = 0; i < typeTitles.count; i++) {

        UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, y, contentView.bounds.size.width, 50)];
        btn.tag = i;
        [btn addTarget:self action:@selector(onFilterTypeTap:) forControlEvents:UIControlEventTouchUpInside];

        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, btn.bounds.size.width - 60, 50)];
        label.text = typeTitles[i];
        label.font = [UIFont systemFontOfSize:16];
        label.textColor = [UIColor blackColor];
        [btn addSubview:label];

        UIImageView *radio = [[UIImageView alloc] initWithFrame:CGRectMake(btn.bounds.size.width - 40, 13, 24, 24)];
        radio.tag = 100 + i;   // so you can update later in refreshFilterOverlay
        radio.image = [self.apptFilterType isEqualToString:typeTitles[i]] ? [UIImage imageNamed:@"radio_check"] : [UIImage imageNamed:@"radio_uncheck"];
        [btn addSubview:radio];

        [contentView addSubview:btn];

        y += 50;
    }

    // Space before next header
    y += 20;

    // 3️⃣ Appointment State Header
    [self createFilterHeaderWithText:@"Appointment State" y:y parent:contentView];
    y += 40;

    // 4️⃣ State Options
    NSArray *timeTitles = @[@"Upcoming", @"History"];
    for (int i = 0; i < timeTitles.count; i++) {

        UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, y, contentView.bounds.size.width, 50)];
        btn.tag = 200 + i;
        [btn addTarget:self action:@selector(onFilterTimeTap:) forControlEvents:UIControlEventTouchUpInside];

        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(16, 0, btn.bounds.size.width - 60, 50)];
        label.text = timeTitles[i];
        label.font = [UIFont systemFontOfSize:16];
        label.textColor = [UIColor blackColor];
        [btn addSubview:label];

        UIImageView *radio = [[UIImageView alloc] initWithFrame:CGRectMake(btn.bounds.size.width - 40, 13, 24, 24)];
        radio.tag = 300 + i;
        radio.image = [self.apptFilterTime isEqualToString:timeTitles[i]] ? [UIImage imageNamed:@"radio_check"] : [UIImage imageNamed:@"radio_uncheck"];
        [btn addSubview:radio];

        [contentView addSubview:btn];

        y += 50;
    }
    // finally add to main view
    [self.view addSubview:self.filterOverlay];
}

- (void)onFilterTypeTap:(UIButton *)sender {
  [self refreshFilterOverlay];
    NSArray *typeTitles = @[@"All", @"Handover", @"Joint Inspection", @"Rectification"];
    NSString *selected = typeTitles[sender.tag];
    self.apptFilterType = selected;
    self.filterOverlay.hidden = YES;
    self.filterOverlay.userInteractionEnabled = NO;
    self.blnLoading = YES;
    [self.loadingView startAnimating];
    // process
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self processAppointmentData:self.arrayAppointmentFull];
        [self.loadingView stopAnimating];
    });
}

- (void)onFilterTimeTap:(UIButton *)sender {
  [self refreshFilterOverlay];
    NSArray *timeTitles = @[@"Upcoming", @"History"];
    NSString *selected = timeTitles[sender.tag - 200];
    self.apptFilterTime = selected;

    self.filterOverlay.hidden = YES;
    self.filterOverlay.userInteractionEnabled = NO;
    self.blnLoading = YES;
    [self.loadingView startAnimating];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)),
                   dispatch_get_main_queue(), ^{
        [self processAppointmentData:self.arrayAppointmentFull];
        [self.loadingView stopAnimating];
    });
}

- (void)hideFilterOverlay {
    self.filterOverlay.hidden = YES;
    self.filterOverlay.userInteractionEnabled = NO;
  
    [self.view bringSubviewToFront:self.topBar];

    [self.view setNeedsLayout];
    [self.view layoutIfNeeded];
}

- (void)refreshFilterOverlay {
    NSArray *typeTitles = @[@"All", @"Handover", @"Joint Inspection", @"Rectification"];
    for (int i = 0; i < typeTitles.count; i++) {
        UIImageView *radio = [self.filterOverlay viewWithTag:100 + i];
        radio.image = [self.apptFilterType isEqualToString:typeTitles[i]]
                      ? [UIImage imageNamed:@"radio_check"]
                      : [UIImage imageNamed:@"radio_uncheck"];
    }

    NSArray *timeTitles = @[@"Upcoming", @"History"];
    for (int i = 0; i < timeTitles.count; i++) {
        UIImageView *radio = [self.filterOverlay viewWithTag:300 + i];
        radio.image = [self.apptFilterTime isEqualToString:timeTitles[i]]
                      ? [UIImage imageNamed:@"radio_check"]
                      : [UIImage imageNamed:@"radio_uncheck"];
    }
}

- (UILabel *)createFilterHeaderWithText:(NSString *)text y:(CGFloat)y parent:(UIView *)parent {
    UILabel *header = [[UILabel alloc] initWithFrame:CGRectMake(16, y, parent.bounds.size.width - 32, 24)];
    header.text = text;
    header.font = [UIFont boldSystemFontOfSize:16];
    header.textColor = [UIColor darkGrayColor];
    [parent addSubview:header];

    // underline
    UIView *underline = [[UIView alloc] initWithFrame:CGRectMake(16, y + 26, parent.bounds.size.width - 32, 1)];
    underline.backgroundColor = [UIColor lightGrayColor];
    [parent addSubview:underline];

    return header;
}

#pragma mark - Loading Overlay
- (void)setupLoadingOverlay {
    self.loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleLarge];
    self.loadingView.center = self.view.center;
    self.loadingView.hidesWhenStopped = YES;
    [self.view addSubview:self.loadingView];
}

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

- (void)onToggleTab {
    if (self.blnLoading) return;
    self.blnLoading = YES;
    [self.loadingView startAnimating];

    [UIView animateWithDuration:0.3 animations:^{
        self.showingCalendar = !self.showingCalendar;
        self.calendarContainer.alpha = self.showingCalendar ? 1 : 0;
        self.listingContainer.alpha = self.showingCalendar ? 0 : 1;
    } completion:^(BOOL finished) {
        self.calendarContainer.hidden = !self.showingCalendar;
        self.listingContainer.hidden = self.showingCalendar;

        NSString *imgName = self.showingCalendar ? @"listing_icon_white" : @"calendar_icon_white";
        [self.toggleTabButton setImage:[UIImage imageNamed:imgName] forState:UIControlStateNormal];

        self.blnLoading = NO;
        [self.loadingView stopAnimating];
    }];
}

- (void)onFilterButton {
    self.filterOverlay.hidden = !self.filterOverlay.hidden;
    self.filterOverlay.userInteractionEnabled = !self.filterOverlay.userInteractionEnabled;
}

- (void)onMakeAppointment {
    AppointmentViewController *vc = [[AppointmentViewController alloc] initWithNibName:nil bundle:nil];
    vc.projectCode = @"PTD197656";
    vc.projectName = @"Ara E`Residence Dev";
    vc.projectId = @"8";
    vc.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentViewController:vc animated:YES completion:nil];
}

#pragma mark - api
- (void)fetchDashboardInfo {
        [self.loadingView startAnimating];

      [DashboardAPIClient fetchDashboardInfo:^(NSDictionary *data, NSError *error) {
        
        [self.loadingView stopAnimating];
        
        if (error) {
          NSLog(@"❌ Failed to load dashboard info: %@", error);
          [self showError:@"Unable to load appointment data."];
          return;
        }
        
        if (![data isKindOfClass:[NSDictionary class]]) {
          [self showError:@"Invalid response from server."];
          return;
        }
        
        NSLog(@"✅ Dashboard Info Loaded!");
        
        // 🔥 Extract appointment array based on your API response shape
        NSArray *appointments = data[@"Data"][@"appointment"];
        if (![appointments isKindOfClass:[NSArray class]]) {
          appointments = @[];
        }

        // Save it for later use
        self.arrayAppointmentFull = appointments;
        
        NSLog(@"📦 Received Appointment Data: %@", self.arrayAppointmentFull);
        NSString *text = [NSString stringWithFormat:@"%@", self.arrayAppointmentFull];
        NSString *docsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
        NSString *filePath = [docsPath stringByAppendingPathComponent:@"appointFull.txt"];
        
        // Convert issueData to a readable string
        NSString *plainText = [NSString stringWithFormat:@"%@", self.arrayAppointmentFull];

        // Write as plain UTF-8 text
        [plainText writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];

        // Log the path so you can find it
        NSLog(@"📁 appointData saved as plain text to: %@", filePath);

        // 🔧 Process filters + convert to sectionized data + refresh UI
        [self processAppointmentData:self.arrayAppointmentFull];
    }];
}

- (void)endRefreshWithNoData {
    self.blnRefreshCalendar = NO;
    [self.listingTable reloadData];
}

- (void)processAppointmentData:(NSArray *)data {
  if (!data) {
    [self.arrayListing removeAllObjects];
    [self.arrayListingSection removeAllObjects];
    [self.listingTable reloadData];
    return;
  }
  
  // 1. Filter by type and time
  NSMutableArray *filtered = [NSMutableArray array];
  NSDateFormatter *df = [[NSDateFormatter alloc] init];
  df.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  df.dateFormat = @"dd MMM yyyy hh:mm a"; // matches RN format 'DD MMM YYYY hh:mm a'
  
  for (NSDictionary *item in data) {
    NSString *apptType = item[@"appointment_type"] ?: @"";
    NSString *startDate = item[@"start_date"] ?: @""; // 'DD MMM YYYY'
    NSString *startTime = item[@"start_time"] ?: @""; // 'hh:mm a'
    
    // combine and parse
    NSString *combined = [NSString stringWithFormat:@"%@ %@", startDate, startTime];
    NSDate *startDateTime = [df dateFromString:combined];
    if (!startDateTime) continue;
    
    // determine upcoming vs history
    BOOL isHistory = [startDateTime timeIntervalSinceNow] < 0;
    
    // time filter
    BOOL timePass = YES;
    if ([self.apptFilterTime isEqualToString:@"History"]) {
      timePass = isHistory;
    } else if ([self.apptFilterTime isEqualToString:@"Upcoming"]) {
      timePass = !isHistory;
    }
    
    // type filter
    BOOL typePass = YES;
    if (![self.apptFilterType isEqualToString:@"All"]) {
      typePass = [apptType isEqualToString:self.apptFilterType];
    }
    
    if (timePass && typePass) {
      [filtered addObject:item];
    }
  }
  
  // 2. Sort
  [filtered sortUsingComparator:^NSComparisonResult(NSDictionary *a, NSDictionary *b) {
    NSString *aCombined = [NSString stringWithFormat:@"%@ %@", a[@"start_date"], a[@"start_time"]];
    NSString *bCombined = [NSString stringWithFormat:@"%@ %@", b[@"start_date"], b[@"start_time"]];
    NSDate *aDate = [df dateFromString:aCombined];
    NSDate *bDate = [df dateFromString:bCombined];
    if (!aDate || !bDate) return NSOrderedSame;
    if ([self.apptFilterTime isEqualToString:@"Upcoming"]) {
      return [aDate compare:bDate];
    } else {
      return [bDate compare:aDate];
    }
  }];
  
  // 3. Build sections grouped by start_date
  [self.arrayListing removeAllObjects];
  [self.arrayListing addObjectsFromArray:filtered];
  
  [self.arrayListingSection removeAllObjects];
  NSMutableDictionary *sectionsDict = [NSMutableDictionary dictionary];
  for (NSDictionary *item in filtered) {
    NSString *dateKey = item[@"start_date"] ?: @"";
    if (!dateKey) continue;
    if (!sectionsDict[dateKey]) sectionsDict[dateKey] = [NSMutableArray array];
    [sectionsDict[dateKey] addObject:item];
  }
  // convert to array preserving order of filtered array
  NSMutableSet *seenDates = [NSMutableSet set];
  for (NSDictionary *item in filtered) {
    NSString *dateKey = item[@"start_date"];
    if (![seenDates containsObject:dateKey]) {
      [seenDates addObject:dateKey];
      NSArray *itemsForDate = sectionsDict[dateKey];
      NSDictionary *section = @{@"title": dateKey, @"data": itemsForDate ?: @[]};
      [self.arrayListingSection addObject:section];
    }
  }
  
  // 4. Build dots map (date -> array of {type,color})
  [self.aryDotsByDate removeAllObjects];
  for (NSDictionary *item in self.arrayListing) {
    NSString *strConvertDate = item[@"start_date"]; // 'DD MMM YYYY'
    // convert to yyyy-MM-dd key
    NSDateFormatter *dfIn = [[NSDateFormatter alloc] init];
    dfIn.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    dfIn.dateFormat = @"dd MMM yyyy";
    NSDate *d = [dfIn dateFromString:strConvertDate];
    NSDateFormatter *dfOut = [[NSDateFormatter alloc] init];
    dfOut.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
    dfOut.dateFormat = @"yyyy-MM-dd";
    NSString *key = [dfOut stringFromDate:d] ?: strConvertDate;
    
    NSString *type = item[@"appointment_type"] ?: @"";
    UIColor *color = [type isEqualToString:@"Handover"] ? [self colorFromHex:@"#047C74"] : [self colorFromHex:@"#C84132"];
    
    NSMutableArray *dots = self.aryDotsByDate[key];
    if (!dots) {
      dots = [NSMutableArray array];
      self.aryDotsByDate[key] = dots;
    }
    [dots addObject:@{@"type": type, @"color": color}];
  }
  
  // 5. refresh table + calendar
  [self.listingTable reloadData];
  
  NSMutableDictionary *dict = [NSMutableDictionary dictionary];
  
  NSDateFormatter *dfIn = [[NSDateFormatter alloc] init];
  dfIn.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  dfIn.dateFormat = @"dd MMM yyyy";
  
  NSDateFormatter *dfOut = [[NSDateFormatter alloc] init];
  dfOut.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  dfOut.dateFormat = @"yyyy-MM-dd";
  
  for (NSDictionary *item in self.arrayListing) {
    
    NSString *startDateStr = item[@"start_date"]; // "27 Nov 2025"
    NSDate *d = [dfIn dateFromString:startDateStr];
    if (!d) continue;
    
    NSString *key = [dfOut stringFromDate:d];
    
    // Status color logic
    NSString *apptType = item[@"appointment_type"];
    UIColor *c = [apptType isEqualToString:@"Handover"]
    ? [self colorFromHex:@"#047C74"]
    : [self colorFromHex:@"#C84132"];
    
    if (!dict[key]) dict[key] = [NSMutableArray array];
    [dict[key] addObject:@{ @"color": c }];
  }
  
  self.aryDotsByDate = dict;
  [self.calendar reloadData];
  
  self.blnRefreshCalendar = YES;
  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    self.blnRefreshCalendar = NO;
  });
  
  self.filterLabel.text = [NSString stringWithFormat:@"Filter by %@ (%@)",
                           self.apptFilterType,
                           self.apptFilterTime];
  
  // Auto-select today or first date that has appointments
  NSDateFormatter *dfToday = [[NSDateFormatter alloc] init];
  dfToday.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  dfToday.dateFormat = @"dd MMM yyyy";
  NSString *todayString = [dfToday stringFromDate:[NSDate date]];
  
  df.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
  df.dateFormat = @"dd MMM yyyy";
  
  NSMutableArray *todayList = [NSMutableArray array];
  
  for (NSDictionary *item in self.arrayListing) {
    if ([item[@"start_date"] isEqualToString:todayString]) {
      [todayList addObject:item];
    }
  }
  
  if (todayList.count > 0) {
    [self.calendar selectDate:[NSDate date] scrollToDate:YES];
    self.agendaList = todayList;
  } else if (self.arrayListing.count > 0) {
    NSDictionary *firstItem = self.arrayListing[0];
    NSDate *firstDate = [df dateFromString:firstItem[@"start_date"]];
    if (firstDate) {
      [self.calendar selectDate:firstDate scrollToDate:YES];
      // populate agendaList for firstDate
      NSMutableArray *firstDateList = [NSMutableArray array];
      for (NSDictionary *item in self.arrayListing) {
        if ([item[@"start_date"] isEqualToString:firstItem[@"start_date"]]) {
          [firstDateList addObject:item];
        }
      }
      self.agendaList = firstDateList;
    }
  }
    [self.agendaTable reloadData];
    [self prepareAgendaSections];
}

- (UIColor *)colorFromHex:(NSString *)hex {
    unsigned rgbValue = 0;
    NSScanner *scanner = [NSScanner scannerWithString:hex];
    [scanner setScanLocation:1]; // bypass '#'
    [scanner scanHexInt:&rgbValue];
    return [UIColor colorWithRed:((rgbValue & 0xFF0000) >> 16)/255.0
                           green:((rgbValue & 0xFF00) >> 8)/255.0
                            blue:(rgbValue & 0xFF)/255.0 alpha:1.0];
}

- (void)showError:(NSString *)message {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Error"
                                                                   message:message
                                                            preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
}

@end
