import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { ProductDataService } from '../../core/products/product-data.service';
import {
	Product,
	ProductCategory,
	ProductListQuery,
	ProductListResult,
	ProductSearchQuery,
	RelatedProductsQuery,
} from '../../core/products/models/product-domain.model';
import { SearchCriteria } from '../../core/products/models/catalog-experience.model';
import { EngagementListQuery, EngagementListResult, Question, RatingSummary, Review, SubmitQuestionInput, SubmitReviewInput } from '../../core/products/models/product-engagement.model';

@Injectable({ providedIn: 'root' })
export class ProductFacade {
	constructor(private readonly productData: ProductDataService) {}

	getProducts(query?: ProductListQuery): Observable<ProductListResult> {
		return this.productData.getProducts(query);
	}

	getProduct(productID: number): Observable<Product> {
		return this.productData.getProduct(productID);
	}

	getCategories(): Observable<ProductCategory[]> {
		return this.productData.getCategories();
	}

	searchProducts(query: ProductSearchQuery): Observable<ProductListResult> {
		return this.productData.searchProducts(query);
	}

	getFeaturedProducts(query?: ProductListQuery): Observable<ProductListResult> {
		return this.productData.getFeaturedProducts(query);
	}

	getLatestProducts(query?: ProductListQuery): Observable<ProductListResult> {
		return this.productData.getLatestProducts(query);
	}

	getProductsByCategory(categoryID: number, query?: ProductListQuery): Observable<ProductListResult> {
		return this.productData.getProductsByCategory(categoryID, query);
	}

	getRelatedProducts(query: RelatedProductsQuery): Observable<ProductListResult> {
		return this.productData.getRelatedProducts(query);
	}

	loadRating(productID: number): Observable<RatingSummary> {
		return this.productData.loadRating(productID);
	}

	loadReviews(productID: number, query?: EngagementListQuery): Observable<EngagementListResult<Review>> {
		return this.productData.loadReviews(productID, query);
	}

	loadQuestions(productID: number, query?: EngagementListQuery): Observable<EngagementListResult<Question>> {
		return this.productData.loadQuestions(productID, query);
	}

	submitReview(productID: number, input: SubmitReviewInput): Observable<void> {
		return this.productData.submitReview(productID, input);
	}

	submitQuestion(productID: number, input: SubmitQuestionInput): Observable<void> {
		return this.productData.submitQuestion(productID, input);
	}

	search(criteria: SearchCriteria): Observable<ProductListResult> {
		const pageSize = Math.max(1, criteria.pageSize ?? 24);
		const page = Math.max(1, criteria.page ?? 1);
		const skip = (page - 1) * pageSize;

		return this.searchProducts({
			search: criteria.keyword ?? '',
			count: pageSize,
			skip,
			categoryIDs: criteria.categoryIDs,
			minPrice: criteria.minPrice,
			maxPrice: criteria.maxPrice,
			sort: criteria.sort === 'discount' ? 'price_desc' : criteria.sort
		});
	}

	filter(criteria: SearchCriteria): Observable<ProductListResult> {
		return this.search(criteria);
	}

	sort(criteria: SearchCriteria): Observable<ProductListResult> {
		return this.search({ ...criteria, sort: criteria.sort ?? 'relevance' });
	}

	loadCatalog(criteria: SearchCriteria): Observable<ProductListResult> {
		const hasKeyword = (criteria.keyword ?? '').trim().length > 0;
		if (hasKeyword) {
			return this.search(criteria);
		}

		const categoryID = criteria.categoryIDs?.[0];
		if (categoryID != null) {
			const pageSize = Math.max(1, criteria.pageSize ?? 24);
			const page = Math.max(1, criteria.page ?? 1);
			const skip = (page - 1) * pageSize;

			return this.getProductsByCategory(categoryID, {
				count: pageSize,
				skip,
				sort: criteria.sort === 'discount' ? 'price_desc' : criteria.sort
			});
		}

		const pageSize = Math.max(1, criteria.pageSize ?? 24);
		const page = Math.max(1, criteria.page ?? 1);
		const skip = (page - 1) * pageSize;

		return this.getProducts({
			count: pageSize,
			skip,
			sort: criteria.sort === 'discount' ? 'price_desc' : criteria.sort
		});
	}
}
