// angular
import { Component, DestroyRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { HttpClient } from '@angular/common/http';

// libs
import Swal from 'sweetalert2';
import { MatDialog } from '@angular/material/dialog';

// app
import { ApiRoutes } from '../../../api-routes';
import { AccountModel } from '../../../model/account.model';
import { AccountCategoryModel } from '../../../model/account.category.model';
import { AccountInviteModel } from '../../../model/account.invite.model';
import { SettingsAccountAddComponent } from './add.account.component';
import { SettingsAccountEditComponent } from './edit.account.component';
import { SettingsAccountAccessComponent } from './access.account.component';
import { AccountCategoryService } from '../../../services/account.category.service';

@Component({
	templateUrl: './account.component.html',
	styleUrls: ['./account.component.scss'],
})
export class SettingsAccountComponent {
	public accountCategories?: AccountCategoryModel[];
	public accounts?: AccountModel[];
	public invites?: AccountInviteModel[];
	public tabIndex = 0;

	private readonly destroyRef = inject(DestroyRef);

	constructor(
		private httpClient: HttpClient,
		private dialogModel: MatDialog,
		private accountCategoryService: AccountCategoryService,
	) {
	}

	ngOnInit(): void {
		this.loadCategories();
		this.loadInvites();
	}

	private loadAccounts(accountToShow?: string) {
		this.httpClient
			.get<AccountModel[]>(ApiRoutes.SettingsAccounts)
			.pipe(takeUntilDestroyed(this.destroyRef))
			.subscribe(data => {
				this.accounts = data;
				if (accountToShow) {
					var idx = -1;
					var account = this.accounts.find(x => x.id === accountToShow);
					if (account && account.categories && account.categories.length > 0) {
						for (var i = 0; i < this.accountCategories!.length; i++) {
							if (account!.categories!.find(c => c.id === this.accountCategories![i].id)) {
								idx = i;
								break;
							}
						}
					}
					this.tabIndex = idx === -1 ? this.accountCategories!.length : idx;
				}
			});
	}

	private loadInvites() {
		return this.httpClient
			.get<AccountInviteModel[]>(ApiRoutes.SettingsAccountInvites)
			.pipe(takeUntilDestroyed(this.destroyRef))
			.subscribe(response => {
				this.invites = response;
			});
	}

	private loadCategories() {
		this.accountCategoryService
			.getCategories()
			.pipe(takeUntilDestroyed(this.destroyRef))
			.subscribe(x => {
				this.accountCategories = x;
				this.loadAccounts();
			});
	}

	public accountInCategory(category?: AccountCategoryModel) {
		if (this.accounts) {
			return this.accounts.filter(acc => (!category && (!acc.categories || acc.categories.length === 0)) || (category && acc.categories && acc.categories.filter(cat => cat.id === category.id).length > 0));
		}
		return null;
	}

	public add() {
		this.dialogModel.open(SettingsAccountAddComponent, {
			width: '640px',
			disableClose: true,
			data: this.accounts,
		}).afterClosed()
			.pipe(takeUntilDestroyed(this.destroyRef))
			.subscribe(x => {
			if (x && x.refresh) {
				this.loadAccounts();
			}
		});
	}

	public edit(account: AccountModel) {
		this.dialogModel.open(SettingsAccountEditComponent, {
			width: '640px',
			disableClose: true,
			data: account,
		}).afterClosed()
			.pipe(takeUntilDestroyed(this.destroyRef))
			.subscribe(x => {
			if (x && x.refresh) {
				this.loadAccounts();
			}
		});
	}

	public remove(account: AccountModel) {
		Swal.fire({
			title: 'Remove account ' + account.name,
			showCancelButton: true,
			confirmButtonText: 'Delete',
			showLoaderOnConfirm: true,
			preConfirm: (name) => {
				return new Promise((resolve, reject) => {
					this.httpClient.delete(ApiRoutes.SettingsAccount.replace(':id', account.id!))
						.pipe(takeUntilDestroyed(this.destroyRef))
						.subscribe(data => {
							resolve(data);
						}, error => {
							Swal.showValidationMessage(error.detail);
							reject();
						});

				}).catch(x => {
					return false;
				});
			},
			allowOutsideClick: () => !Swal.isLoading(),
		}).then((result) => {
			this.loadAccounts();
		});
	}

	public access(account: AccountModel) {
		this.dialogModel.open(SettingsAccountAccessComponent, {
			width: '640px',
			disableClose: true,
			data: account,
		}).afterClosed()
			.pipe(takeUntilDestroyed(this.destroyRef))
			.subscribe(x => {
			if (x && x.refresh) {
				this.loadAccounts();
			}
		});
	}

	public startInvite(invite: AccountInviteModel) {
		Swal.fire({
			title: 'Accept to invite the account "' + invite.account + '"',
			input: 'text',
			inputLabel: 'Accept with name',
			inputValue: invite.account,
			showDenyButton: true,
			showCancelButton: true,
			confirmButtonText: 'Accept',
			denyButtonText: 'Reject',
			showLoaderOnConfirm: true,
			preConfirm: (input) => {
				return new Promise((resolve, reject) => {
					this.httpClient.post(ApiRoutes.SettingsAccountInviteAccept.replace(':id', invite.id!), { name: input })
						.pipe(takeUntilDestroyed(this.destroyRef))
						.subscribe(data => {
							resolve(data);
						}, error => {
							Swal.showValidationMessage(error);
							reject();
						});

				}).catch(x => {
					return false;
				});
			},
			preDeny: (x) => {
				return new Promise((resolve, reject) => {
					this.httpClient.post(ApiRoutes.SettingsAccountInviteReject.replace(':id', invite.id!), null)
						.pipe(takeUntilDestroyed(this.destroyRef))
						.subscribe(data => {
							resolve(data);
						}, error => {
							Swal.showValidationMessage(error.detail);
							reject();
						});

				}).catch(x => {
					return false;
				});
			},
			allowOutsideClick: () => !Swal.isLoading(),
		}).then((result) => {
			var id;
			if (result.value) {
				var account = result.value as AccountModel;
				id = account.id;
			}
			this.loadInvites();
			this.loadAccounts(id);
		});

	}
}
