import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';

import { NotifierService } from './notifier.service';

import { User } from './user.model';
import { Owner } from './owner.model';
import { Country } from './country.model';

import { ConfigData } from './configdata';

var Buffer = require('buffer/').Buffer;

@Injectable({providedIn: 'root'})

export class UserService{
	beUrl = ConfigData.Be_URL;
	private dataStore: { user: User, owner: Owner, countries: Country[]} = { 
		user: {
			address: '',
			session: '',
			blocktime: 0,
			pin: '',
			validated: false
		},
		owner: {
			address: '',
			name: '',
			currency: 'usd',
			tax: false,
			taxValue: 0,
			vat: false,
			vatValue: 0,
			paid: false,
			zats: false,
			invoices: false,
			expiration: new Date(Date.now()).toISOString(),
			payconf: false,
			crmToken: ''
		},
		countries: []
	};
	private uZaddr = '';
	private session: string | null = '';
	private _uZaddrUpdated: BehaviorSubject<string> = new BehaviorSubject(this.uZaddr);
	private _userUpdated: BehaviorSubject<User> = new BehaviorSubject(this.dataStore.user);
	private _ownerUpdated: BehaviorSubject<Owner> = new BehaviorSubject(this.dataStore.owner);
	private _paidUpdated: BehaviorSubject<boolean> = new BehaviorSubject(this.dataStore.owner.paid);
	private _countriesUpdated: BehaviorSubject<Country[]> = new BehaviorSubject(this.dataStore.countries);
	public readonly uZaddrUpdate: Observable<string> = this._uZaddrUpdated.asObservable();
	public readonly ownerUpdate: Observable<Owner> = this._ownerUpdated.asObservable();
	public readonly userUpdate: Observable<User> = this._userUpdated.asObservable();
	public readonly paidUpdate: Observable<boolean> = this._paidUpdated.asObservable();
	public readonly countriesUpdate: Observable<Country[]> = this._countriesUpdated.asObservable();
	private reqHeaders: HttpHeaders;
	private reqParams: HttpParams;

	constructor(private http: HttpClient,
				private notifierService : NotifierService ){
		var auth = 'Basic ' + Buffer.from(ConfigData.UsrPwd).toString('base64');
		this.reqHeaders = new HttpHeaders().set('Authorization', auth);
		//console.log('US:', this.reqHeaders);
		this.session = localStorage.getItem('s4z_token');
		this.reqParams = new HttpParams().append('session', this.session!);
		//if (this.session != null) {
			//this.findUser();
		//}
	}

	getCountries() {
		let obs = this.http.get<{message: string, countries: any}>(this.beUrl+'api/countries', { headers: this.reqHeaders, params: this.reqParams, observe: 'response'});

		obs.subscribe((CountryResponse) => {
			if (CountryResponse.status == 200) {
				this.dataStore.countries = CountryResponse.body!.countries;
				this._countriesUpdated.next(Object.assign({}, this.dataStore).countries);
			}
		});
	}

	checkUser() {
		if (this.session != null) {
			console.log('calling checkUser');
			let obs = this.http.get<{validated: boolean}>(this.beUrl + 'checkuser', {headers: this.reqHeaders, params: this.reqParams, observe: 'response'});

			return obs;
		} else {
			return null;
		}
	}

	findUser() {
		if (this.session != null) {
			let obs = this.http.get<{message: string, user: any}>(this.beUrl+'api/user', { headers: this.reqHeaders, params: this.reqParams, observe: 'response'});

			obs.subscribe((UserDataResponse) => {
				//console.log(UserDataResponse.status);
				if (UserDataResponse.status == 200){
					this.dataStore.user = UserDataResponse.body!.user;
					//console.log(`US: Found user, returning it`);
					this._uZaddrUpdated.next(Object.assign({},this.dataStore).user.address);
					this._userUpdated.next(Object.assign({}, this.dataStore).user);
					this.getOwner();
				} else {
					this.dataStore.user = {
						address: '',
						session: '',
						blocktime: 0,
						pin: '',
						validated: false
					};
					this._uZaddrUpdated.next(Object.assign({},this.dataStore).user.address);
					this._userUpdated.next(Object.assign({}, this.dataStore).user);
					//console.log('US: Did not find user');
				}
			});

			return obs;
		} else {
			console.log('No session loaded');
			return null;
		}
	}
	
	validateUser(pinString:string){
		const params = this.reqParams.append('pin', pinString);
		let obs = this.http.post(this.beUrl+'validateuser', {}, {headers: this.reqHeaders, params: params, observe: 'response'});
		obs.subscribe((responseData) => {
			if (responseData.status == 202) {
				console.log('Pin validated!');
				return true;
			} else {
				console.log('Wrong pin!');
				return false;
			}
		});

		return obs;
	}

	addOwner(oData: {first: string, last: string, phone: string, name: string, street: string, city: string, state: string, postal: string, country: string, email: string, website: string}) {

		let obs = this.http.post(this.beUrl+'api/owner', {payload: oData}, {headers: this.reqHeaders, params: this.reqParams});

		obs.subscribe({
			next: () => {
				//console.log("Entra a console log");
				this.getOwner();
			},
			error: (error) => {
				//console.log("Status is : [" + error.status + "]");
				if ( error.status = 500 ) {
					this.notifierService .showNotification("Invalid Viewing Key, changes not saved!!","Close",'error');
				};
			}
		});

		return obs;
	}

	getOwner() {
		//console.log('getOwner', address);
		//const ownParams = this.reqParams.append('address', address)
		let obs = this.http.get<{message:string, owner: any}>(this.beUrl+'api/owner', { headers: this.reqHeaders, params: this.reqParams, observe: 'response'});

		obs.subscribe((OwnerDataResponse) => {
			//console.log('api/getowner', OwnerDataResponse.status);
			if (OwnerDataResponse.status == 200) {
				this.dataStore.owner = OwnerDataResponse.body!.owner;
				//console.log('getOwner object', this.dataStore.owner);
				//console.log('Payment Conf.?: [' + ( this.dataStore.owner.payconf ? "On]" : "Off]") );
				//console.log('Viewkey : [' + this.dataStore.owner.viewkey + "]");
				this._ownerUpdated.next(Object.assign({},this.dataStore).owner);
				this._paidUpdated.next(Object.assign({}, this.dataStore).owner.paid);
			}
		}); 

		return obs;
	}

	deleteUser() {
		let obs = this.http.delete<{message: string}>(this.beUrl+'api/user/'+this.dataStore.user._id, {headers: this.reqHeaders, params: this.reqParams });

		obs.subscribe({next: () => {
			//console.log('User delete request sent.');
			this.findUser();
		}});

		return obs;
	}

	saveSettings(o: Owner) {
	}

	currentOwner() : Owner {
		return this.dataStore.owner;
	}

}
