import { formatDate } from "@angular/common";
import { Component, EventEmitter, Input, Output, OnInit } from "@angular/core";
import { firstValueFrom, map, Observable } from "rxjs";

import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
import { PolicyType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
import { DialogService, ToastService } from "@bitwarden/components";

@Component({
  selector: "[sponsoring-org-row]",
  templateUrl: "sponsoring-org-row.component.html",
})
export class SponsoringOrgRowComponent implements OnInit {
  @Input() sponsoringOrg: Organization = null;
  @Input() isSelfHosted = false;

  @Output() sponsorshipRemoved = new EventEmitter();

  statusMessage = "loading";
  statusClass: "tw-text-success" | "tw-text-danger" = "tw-text-success";
  isFreeFamilyPolicyEnabled$: Observable<boolean>;
  isFreeFamilyFlagEnabled: boolean;
  private locale = "";

  constructor(
    private apiService: ApiService,
    private i18nService: I18nService,
    private logService: LogService,
    private platformUtilsService: PlatformUtilsService,
    private dialogService: DialogService,
    private toastService: ToastService,
    private configService: ConfigService,
    private policyService: PolicyService,
  ) {}

  async ngOnInit() {
    this.locale = await firstValueFrom(this.i18nService.locale$);

    this.setStatus(
      this.isSelfHosted,
      this.sponsoringOrg.familySponsorshipToDelete,
      this.sponsoringOrg.familySponsorshipValidUntil,
      this.sponsoringOrg.familySponsorshipLastSyncDate,
    );
    this.isFreeFamilyFlagEnabled = await this.configService.getFeatureFlag(
      FeatureFlag.DisableFreeFamiliesSponsorship,
    );

    if (this.isFreeFamilyFlagEnabled) {
      this.isFreeFamilyPolicyEnabled$ = this.policyService
        .getAll$(PolicyType.FreeFamiliesSponsorshipPolicy)
        .pipe(
          map(
            (policies) =>
              Array.isArray(policies) &&
              policies.some(
                (policy) => policy.organizationId === this.sponsoringOrg.id && policy.enabled,
              ),
          ),
        );
    }
  }

  async revokeSponsorship() {
    try {
      await this.doRevokeSponsorship();
    } catch (e) {
      this.logService.error(e);
    }
  }

  async resendEmail() {
    await this.apiService.postResendSponsorshipOffer(this.sponsoringOrg.id);
    this.toastService.showToast({
      variant: "success",
      title: null,
      message: this.i18nService.t("emailSent"),
    });
  }

  get isSentAwaitingSync() {
    return this.isSelfHosted && !this.sponsoringOrg.familySponsorshipLastSyncDate;
  }

  private async doRevokeSponsorship() {
    const confirmed = await this.dialogService.openSimpleDialog({
      title: `${this.i18nService.t("remove")} ${this.sponsoringOrg.familySponsorshipFriendlyName}?`,
      content: { key: "revokeSponsorshipConfirmation" },
      acceptButtonText: { key: "remove" },
      type: "warning",
    });

    if (!confirmed) {
      return;
    }

    await this.apiService.deleteRevokeSponsorship(this.sponsoringOrg.id);
    this.toastService.showToast({
      variant: "success",
      title: null,
      message: this.i18nService.t("reclaimedFreePlan"),
    });
    this.sponsorshipRemoved.emit();
  }

  private setStatus(
    selfHosted: boolean,
    toDelete?: boolean,
    validUntil?: Date,
    lastSyncDate?: Date,
  ) {
    /*
     * Possible Statuses:
     * Requested (self-hosted only)
     * Sent
     * Active
     * RequestRevoke
     * RevokeWhenExpired
     */

    if (toDelete && validUntil) {
      // They want to delete but there is a valid until date which means there is an active sponsorship
      this.statusMessage = this.i18nService.t(
        "revokeWhenExpired",
        formatDate(validUntil, "MM/dd/yyyy", this.locale),
      );
      this.statusClass = "tw-text-danger";
    } else if (toDelete) {
      // They want to delete and we don't have a valid until date so we can
      // this should only happen on a self-hosted install
      this.statusMessage = this.i18nService.t("requestRemoved");
      this.statusClass = "tw-text-danger";
    } else if (validUntil) {
      // They don't want to delete and they have a valid until date
      // that means they are actively sponsoring someone
      this.statusMessage = this.i18nService.t("active");
      this.statusClass = "tw-text-success";
    } else if (selfHosted && lastSyncDate) {
      // We are on a self-hosted install and it has been synced but we have not gotten
      // a valid until date so we can't know if they are actively sponsoring someone
      this.statusMessage = this.i18nService.t("sent");
      this.statusClass = "tw-text-success";
    } else if (!selfHosted) {
      // We are in cloud and all other status checks have been false therefore we have
      // sent the request but it hasn't been accepted yet
      this.statusMessage = this.i18nService.t("sent");
      this.statusClass = "tw-text-success";
    } else {
      // We are on a self-hosted install and we have not synced yet
      this.statusMessage = this.i18nService.t("requested");
      this.statusClass = "tw-text-success";
    }
  }
}
