import { Maybe } from '@/core';
// import { ICustomerResponse } from '@/modules/customers/models';
import { IGoodCategoryResponse, IGoodResponse } from '@/domains/pos/models/good.io';
import { CustomerType } from '@/shared/localEnum/constants/customerTypes';
import { createUUID, JALALI_DATE_FORMATS, nowJalali } from '@/utils';
import { computed, inject, Injectable, signal } from '@angular/core';
import { catchError, finalize, map, throwError } from 'rxjs';
import { ICustomer, IPayment, IPosOrderRequest, IPosOrderResponse } from '../models';
import { IPosInOrderGood, IPosOrderItem } from '../models/types';
import { PosService } from '../services/main.service';

export type TViewType = 'list' | 'grid';

interface IPosLandingState {
  getGoodsLoading: boolean;
  goods: Maybe<IGoodResponse[]>;
  getGoodCategoriesLoading: boolean;
  goodCategories: Maybe<IGoodCategoryResponse[]>;
  activeGoodCategory: Maybe<string>;
  inOrderGoods: IPosInOrderGood[];
  viewType: TViewType;
  searchQuery: string;
  customerDetails: {
    customer_id?: string;
    info?: ICustomer;
    type: CustomerType;
  };
  invoiceDate: string;
  orderNote?: string;
  payments: IPayment;
  submitOrderLoading: boolean;
}

export const INITIAL_POS_STATE: IPosLandingState = {
  getGoodsLoading: true,
  goods: null,
  getGoodCategoriesLoading: true,
  goodCategories: null,
  activeGoodCategory: null,
  inOrderGoods: [],
  viewType: 'grid',
  searchQuery: '',
  customerDetails: {
    type: CustomerType.UNKNOWN,
  },
  invoiceDate: nowJalali(JALALI_DATE_FORMATS.NUMERIC_WITH_FULL_TIME),
  payments: {
    cash: 0,
    set_off: 0,
    terminals: [],
  },
  submitOrderLoading: false,
};

@Injectable({ providedIn: 'any' })
export class PosLandingStore {
  private readonly service = inject(PosService);

  private state$ = signal<IPosLandingState>({ ...INITIAL_POS_STATE });

  readonly goods = computed(() => this.state$().goods);

  readonly getGoodsLoading = computed(() => this.state$().getGoodsLoading);
  readonly inOrderGoods = computed(() => this.state$().inOrderGoods);
  readonly goodCategories = computed(() => this.state$().goodCategories);
  readonly getGoodCategoriesLoading = computed(() => this.state$().getGoodCategoriesLoading);
  readonly activeGoodCategory = computed(() => this.state$().activeGoodCategory);
  readonly viewType = computed(() => this.state$().viewType);
  readonly searchQuery = computed(() => this.state$().searchQuery);
  readonly submitOrderLoading = computed(() => this.state$().submitOrderLoading);
  readonly activatedCategoryGoods = computed(() => {
    if (!this.activeGoodCategory()) {
      return this.state$().goods;
    }
    return this.state$().goods?.filter((s) => s.category.id === this.state$().activeGoodCategory);
  });
  readonly filteredGoods = computed(() =>
    this.activatedCategoryGoods()?.filter((good) => good.name.includes(this.state$().searchQuery)),
  );

  readonly customer = computed(() => this.state$().customerDetails);
  readonly invoiceDate = computed(() => this.state$().invoiceDate);
  readonly payments = computed(() => this.state$().payments);

  readonly orderPricingInfo = computed(() => {
    const totalAmount = 0;
    const taxAmount = totalAmount * 0.1;
    return {
      totalItems: this.inOrderGoods().length,
      totalBaseAmount: this.inOrderGoods().reduce((acc, curr) => acc + curr.base_total_amount, 0),
      totalAmount: this.inOrderGoods().reduce((acc, curr) => acc + curr.total_amount, 0),
      taxAmount: this.inOrderGoods().reduce((acc, curr) => acc + curr.tax_amount, 0),
      discountAmount: this.inOrderGoods().reduce((acc, curr) => acc + curr.discount_amount, 0),
      payableAmount: totalAmount + taxAmount,
    };
  });

  setState(partial: Partial<IPosLandingState>) {
    this.state$.set({ ...this.state$(), ...partial });
  }

  reset() {
    this.state$.set({ ...INITIAL_POS_STATE });
  }

  initial() {
    this.getGoods();
    this.getGoodCategories();
  }

  fillInitial(data: Partial<IPosLandingState>) {
    this.state$.set({ ...INITIAL_POS_STATE, ...data });
  }

  getGoods() {
    this.setState({ getGoodsLoading: true });
    this.service.getGoods(this.state$().searchQuery).subscribe({
      next: (res) => {
        this.setState({ goods: res.data, getGoodsLoading: false });
      },
      error: () => {
        this.setState({ getGoodsLoading: false });
      },
    });
  }

  getGoodCategories() {
    this.setState({ getGoodCategoriesLoading: true });
    this.service
      .getGoodCategories()
      .pipe(
        map((res) => {
          return [
            {
              id: '',
              name: 'همه',
              goods_count: res.data.reduce((acc, curr) => acc + curr.goods_count, 0),
            },
            ...res.data,
          ];
        }),
      )
      .subscribe({
        next: (res) => {
          this.setState({
            goodCategories: res,
            getGoodCategoriesLoading: false,
            activeGoodCategory: res[0]?.id,
          });
        },
        error: () => {
          this.setState({ getGoodCategoriesLoading: false });
        },
      });
  }

  changeActiveCategory(categoryId: string) {
    this.setState({ activeGoodCategory: categoryId });
  }

  editInOrderGoods(inOrderGood: IPosInOrderGood) {
    this.setState({
      inOrderGoods: [...this.inOrderGoods()].map((orderItem) => {
        if (inOrderGood.id === orderItem.id) {
          return inOrderGood;
        }
        return orderItem;
      }),
    });
  }
  addToInOrderGoods(goodId: string, payload: IPosOrderItem) {
    const good = this.state$().goods?.find((s) => s.id === goodId);

    if (!good) return;

    this.setState({
      inOrderGoods: [
        ...this.inOrderGoods(),
        {
          id: createUUID(),
          good,
          ...payload,
        },
      ],
    });
  }

  removeFromInOrderGoods(orderItemId: string) {
    this.setState({
      inOrderGoods: this.state$().inOrderGoods.filter((p) => p.id !== orderItemId),
    });
  }

  updateViewType(viewType: TViewType) {
    this.setState({ viewType });
  }
  updateSearchQuery(searchQuery: string) {
    this.setState({ searchQuery });
  }

  filterGoods() {}

  resetInOrderGoods() {
    this.setState({ inOrderGoods: [] });
  }

  setCustomer(customer: { customer_id?: string; info?: ICustomer; type: CustomerType }) {
    this.setState({ customerDetails: customer });
  }

  setPayment(payments: IPayment) {
    this.setState({ payments });
  }

  submitOrder() {
    this.setState({ submitOrderLoading: true });
    const orderPayload: IPosOrderRequest = {
      customer_id: this.customer().customer_id,
      customer_type: this.customer().type,
      customer: this.customer().info,
      items: this.inOrderGoods().map(({ good, ...rest }) => ({
        ...rest,
        good_id: good.id,
        unit_type: good.unit_type,
      })),
      invoice_date: new Date().toISOString(),
      payments: this.payments(),
      total_amount: this.orderPricingInfo().totalAmount,
    };

    let res: Maybe<IPosOrderResponse> = null;

    return this.service.submitOrder(orderPayload).pipe(
      finalize(() => {
        this.setState({ submitOrderLoading: false });
      }),
      catchError((error) => throwError(() => error)),

      map((_res) => {
        if (_res) {
          this.setState({
            inOrderGoods: [],
            customerDetails: {
              type: CustomerType.UNKNOWN,
            },
            invoiceDate: nowJalali(JALALI_DATE_FORMATS.NUMERIC),
            payments: {
              cash: 0,
              set_off: 0,
              terminals: [],
            },
            orderNote: '',
          });
        }

        return _res;
      }),
    );
  }
}
