// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "ios/chrome/browser/settings/manage_accounts/ui/manage_accounts_table_view_controller.h"

#import "base/apple/foundation_util.h"
#import "base/metrics/user_metrics.h"
#import "base/notreached.h"
#import "google_apis/gaia/gaia_id.h"
#import "ios/chrome/browser/authentication/ui_bundled/cells/table_view_account_item.h"
#import "ios/chrome/browser/settings/manage_accounts/public/manage_accounts_table_view_controller_constants.h"
#import "ios/chrome/browser/settings/manage_accounts/ui/identity_view_item.h"
#import "ios/chrome/browser/settings/manage_accounts/ui/manage_accounts_model_identity_data_source.h"
#import "ios/chrome/browser/settings/manage_accounts/ui/manage_accounts_mutator.h"
#import "ios/chrome/browser/shared/model/profile/features.h"
#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_text_item.h"
#import "ios/chrome/browser/shared/ui/table_view/table_view_utils.h"
#import "ios/chrome/browser/signin/model/constants.h"
#import "ios/chrome/common/ui/colors/semantic_color_names.h"
#import "ios/chrome/grit/ios_strings.h"
#import "ui/base/l10n/l10n_util_mac.h"

namespace {

typedef NS_ENUM(NSInteger, EditAccountListSectionIdentifier) {
  SectionIdentifierPrimaryAccount = kSectionIdentifierEnumZero,
  SectionIdentifierSecondaryAccount,
};

typedef NS_ENUM(NSInteger, EditAccountListItemType) {
  // Account item.
  ItemTypeAccount = kItemTypeEnumZero,
  // Remove account item.
  ItemTypeRemoveAccount,
  // Add account item.
  ItemTypeAddAccount,
  // Sign out item.
  ItemTypeSignOut,
};

}  // namespace

@interface ManageAccountsTableViewController () {
  // Enable lookup of item corresponding to a given IdentityViewItem GAIA ID
  // string.
  base::flat_map<GaiaId, TableViewItem*> _identityMap;

  // If YES, offers the sign-out button on the UI.
  BOOL _offerSignout;
}

@end

@implementation ManageAccountsTableViewController

@synthesize modelIdentityDataSource;

- (instancetype)initWithOfferSignout:(BOOL)offerSignout {
  self = [super initWithStyle:ChromeTableViewStyle()];
  if (self) {
    _offerSignout = offerSignout;
  }

  return self;
}

#pragma mark - UIViewController

- (void)viewDidLoad {
  [super viewDidLoad];
  self.tableView.accessibilityIdentifier = kSettingsEditAccountListTableViewId;

  [self loadModel];
}

#pragma mark - SettingsRootTableViewController

- (void)loadModel {
  self.title = l10n_util::GetNSString(IDS_IOS_DEVICE_ACCOUNTS_MANAGEMENT);

  [super loadModel];

  TableViewModel* model = self.tableViewModel;

  base::flat_map<GaiaId, TableViewItem*> mutableIdentityMap;

  NSString* authenticatedEmail =
      [self.modelIdentityDataSource primaryIdentityViewItem].userEmail;

  NSInteger nextSection = SectionIdentifierSecondaryAccount;

  for (const auto& identityViewItem :
       [self.modelIdentityDataSource identityViewItems]) {
    CHECK(identityViewItem);

    TableViewItem* accountItem =
        [self accountItemWithIdentityViewItem:identityViewItem];
    TableViewItem* removeAccountItem =
        [self removeAccountItemWithIdentityViewItem:identityViewItem];
    NSInteger sectionNumber;
    if ([identityViewItem.userEmail isEqualToString:authenticatedEmail]) {
      [model insertSectionWithIdentifier:SectionIdentifierPrimaryAccount
                                 atIndex:0];
      sectionNumber = SectionIdentifierPrimaryAccount;
    } else {
      [model addSectionWithIdentifier:nextSection];
      sectionNumber = nextSection++;
    }
    [model addItem:accountItem toSectionWithIdentifier:sectionNumber];
    [model addItem:removeAccountItem toSectionWithIdentifier:sectionNumber];
    mutableIdentityMap[identityViewItem.gaiaID] = accountItem;
  }

  TableViewItem* addAccountItem = [self addAccountItem];
  [model addSectionWithIdentifier:nextSection];
  [model addItem:addAccountItem toSectionWithIdentifier:nextSection++];

  if (_offerSignout) {
    TableViewItem* signOutItem = [self signOutItem];
    [model addSectionWithIdentifier:nextSection];
    [model addItem:signOutItem toSectionWithIdentifier:nextSection++];
  }

  _identityMap = mutableIdentityMap;
}

#pragma mark - Model objects

- (TableViewItem*)accountItemWithIdentityViewItem:
    (IdentityViewItem*)identityViewItem {
  TableViewAccountItem* item =
      [[TableViewAccountItem alloc] initWithType:ItemTypeAccount];
  [self updateAccountItem:item withIdentityViewItem:identityViewItem];
  return item;
}

- (void)updateAccountItem:(TableViewAccountItem*)item
     withIdentityViewItem:(IdentityViewItem*)identityViewItem {
  item.image = identityViewItem.avatar;
  NSString* name = identityViewItem.userFullName;
  NSString* email = identityViewItem.userEmail;
  if (name) {
    item.text = name;
    item.detailText = email;
  } else {
    item.text = email;
  }
  item.accessibilityIdentifier = identityViewItem.accessibilityIdentifier;
  item.mode = TableViewAccountModeNonTappable;
  item.accessoryType = UITableViewCellAccessoryNone;
  item.accessibilityTraits = UIAccessibilityTraitStaticText;
  if (identityViewItem.managed) {
    item.detailImage = TableViewAccountDetailImage::kManaged;
  }
}

- (TableViewItem*)removeAccountItemWithIdentityViewItem:
    (IdentityViewItem*)identityViewItem {
  TableViewTextItem* item =
      [[TableViewTextItem alloc] initWithType:ItemTypeRemoveAccount];
  item.text = l10n_util::GetNSString(IDS_IOS_REMOVE_GOOGLE_ACCOUNT_TITLE);
  item.accessibilityIdentifier =
      [kSettingsAccountsRemoveAccountButtonAccessibilityIdentifier
          stringByAppendingString:identityViewItem.accessibilityIdentifier];
  item.textColor = [UIColor colorNamed:kBlueColor];
  item.accessibilityTraits = UIAccessibilityTraitButton;
  return item;
}

- (TableViewItem*)addAccountItem {
  TableViewTextItem* item =
      [[TableViewTextItem alloc] initWithType:ItemTypeAddAccount];
  item.text =
      l10n_util::GetNSString(IDS_IOS_OPTIONS_ACCOUNTS_ADD_ACCOUNT_BUTTON);
  item.accessibilityIdentifier = kSettingsAccountsTableViewAddAccountCellId;
  item.textColor = [UIColor colorNamed:kBlueColor];
  item.accessibilityTraits = UIAccessibilityTraitButton;
  return item;
}

- (TableViewItem*)signOutItem {
  TableViewTextItem* item =
      [[TableViewTextItem alloc] initWithType:ItemTypeSignOut];
  item.text =
      l10n_util::GetNSString(IDS_IOS_DISCONNECT_DIALOG_CONTINUE_BUTTON_MOBILE);
  item.accessibilityIdentifier = kSettingsAccountsTableViewSignoutCellId;
  item.textColor = [UIColor colorNamed:kBlueColor];
  item.accessibilityTraits = UIAccessibilityTraitButton;
  return item;
}

#pragma mark - UITableViewDelegate

- (void)tableView:(UITableView*)tableView
    didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
  [super tableView:tableView didSelectRowAtIndexPath:indexPath];

  EditAccountListItemType itemType = static_cast<EditAccountListItemType>(
      [self.tableViewModel itemTypeForIndexPath:indexPath]);
  switch (itemType) {
    case ItemTypeAccount:
      return;
    case ItemTypeRemoveAccount: {
      NSIndexPath* accountItemIndexPath =
          [NSIndexPath indexPathForRow:0 inSection:indexPath.section];
      TableViewAccountItem* accountItem =
          base::apple::ObjCCastStrict<TableViewAccountItem>(
              [self.tableViewModel itemAtIndexPath:accountItemIndexPath]);
      UIView* itemView =
          [[tableView cellForRowAtIndexPath:indexPath] contentView];
      base::RecordAction(base::UserMetricsAction(
          "Signin_AccountsTableView_AccountDetail_RemoveAccount"));
      [self.mutator
          requestRemoveIdentityWithGaiaID:[self
                                              gaiaIDWithAccountItem:accountItem]
                                 itemView:itemView];
      break;
    }
    case ItemTypeAddAccount:
      base::RecordAction(
          base::UserMetricsAction("Signin_AccountsTableView_AddAccount"));
      [self.mutator requestAddIdentityToDevice];
      break;
    case ItemTypeSignOut:
      base::RecordAction(
          base::UserMetricsAction("Signin_AccountsTableView_SignOut"));
      UIView* itemView =
          [[tableView cellForRowAtIndexPath:indexPath] contentView];
      [self.mutator requestSignOutWithItemView:itemView];
      break;
  }

  [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}

#pragma mark - ManageAccountsConsumer

- (void)reloadAllItems {
  if (!self.tableViewModel) {
    // No need to reload since the model has not been loaded yet.
    return;
  }
  [self reloadData];
}

- (void)updateIdentityViewItem:(IdentityViewItem*)identityViewItem {
  TableViewAccountItem* item =
      base::apple::ObjCCastStrict<TableViewAccountItem>(
          _identityMap[identityViewItem.gaiaID]);
  if (!item) {
    return;
  }
  [self updateAccountItem:item withIdentityViewItem:identityViewItem];
  NSIndexPath* indexPath = [self.tableViewModel indexPathForItem:item];
  [self.tableView reloadRowsAtIndexPaths:@[ indexPath ]
                        withRowAnimation:UITableViewRowAnimationAutomatic];
}

- (void)popView {
  // No need to implement this here as the coordinator is handling this. Once
  // LegacyAccountsTableViewController is deleted, this method can be remove
  // from ManageAccountsConsumer
}

#pragma mark - Private

- (GaiaId)gaiaIDWithAccountItem:(TableViewItem*)accountItem {
  for (const std::pair<GaiaId, TableViewItem*>& id_item : _identityMap) {
    if (id_item.second == accountItem) {
      return id_item.first;
    }
  }
  return GaiaId();
}

#pragma mark - UIAdaptivePresentationControllerDelegate

- (void)presentationControllerDidDismiss:
    (UIPresentationController*)presentationController {
  base::RecordAction(
      base::UserMetricsAction("IOSAccountsSettingsCloseWithSwipe"));
}

#pragma mark - SettingsControllerProtocol

- (void)reportDismissalUserAction {
  base::RecordAction(base::UserMetricsAction("MobileAccountsSettingsClose"));
}

- (void)reportBackUserAction {
  base::RecordAction(base::UserMetricsAction("MobileAccountsSettingsBack"));
}

@end
