import { inject, Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { OdataGridHelper } from '../_shared/utils/odata-grid-helper';
import { map, Observable } from 'rxjs';
import * as util from '../_shared/utils/util';
import { State } from '@progress/kendo-data-query';

export interface Item {
  actualTypeId: number;
  supplyNomId: number;
  marketNomId: number;
  lastTransferId: number;
  lastTransferNum: string;
  date: Date;
  day: number;
  counterpartyName: string;
  deliveryCounterpartyShort: string;
  receiptCounterpartyShort: string;
  ticketNum: string;
  deliveryDealNum: string;
  receiptDealNum: string;
  pipeName: string;
  pipeId: number;
  pointName: string;
  pointId: number;
  nomVolume: number;
  actualVolume: number;
  price: number;
  priceAdj: number;
  actualFee: number;
  adjustment: number;
  transportRate: number;
  invoicePrice: number;
  amount: number;
  receiptMeterName: string;
  receiptMeterId: number;
  deliveryMeterName: string;
  deliveryMeterId: number;
  tneMeterName: string;
  tneMeterId: number;
  pipeContractName: string;
  isVolumeEdited: boolean;
  isPriceEdited: boolean;
  isPriceAdjEdited: boolean;
  isActualFeeEdited: boolean;
  isAdjustmentEdited: boolean;
  isTransportRateEdited: boolean;
  saveDate: Date;
  dealId: number;
  transferDealId: number;
  isLinked: boolean;
  isLinkEdited: boolean;
  hasTransfers: boolean;
  transferCount: number;
  tneMeterDeductLegNum: number;
  transportCalcText: string;
  priceAdjCalcText: string;
  priceCalcText: string;
}

export interface UserSelections {
  productionPeriod: Date;
  actualTypeId: number;
  pipelineId: number;
  pipeContractId: number;
  meterId: number;
  counterpartyId: number;
}

export enum SaveType {
  New = 1,
  Normal = 2
}

export interface RequiredData {
  hasModifyPermission: boolean;
  counterparties: CounterpartyItem[];
  meters: MeterItem[];
  actualTypes: ActualTypeItem[];
  pipelines: PipelineItem[];
  points: PointItem[];
  pipeContracts: PipeContractItem[];
}

export interface PipeContractItem {
  pipeContractId: number;
  pipeContractName: string;
  pipeId: number;
}

export interface PointItem {
  pointId: number;
  pointName: string;
}

export interface PipelineItem {
  pipelineId: number;
  pipelineName: string;
}

export interface ActualTypeItem {
  actualTypeId: number;
  actualTypeName: string;
}

export interface CounterpartyItem {
  counterpartyId: number;
  counterpartyName: string;
}

export interface MeterItem {
  meterId: number;
  meterName: string;
  pipeId: number;
}

export interface CellEditItem {
  actualVolume: number;
  price: number;
  priceAdj: number;
  actualFee: number;
  adjustment: number;
  transportRate: number;
  isLinked: boolean;
}

export interface FilterItem {
  id: number;
  userId: number;
  productId: number;
  state: string;
}

export interface ExternalParams {
  topless: number,
  dealNum: string
  dealId: number
}

export interface SetTneMeterPayload {
  clickedItem: Item;
  tneMeterItems: Item[];
}

@Injectable({
  providedIn: 'root'
})
export class ActualsCrudeService extends OdataGridHelper {
  private baseUrl = `${window.location.origin}/api/ActualsCrude`;
  http = inject(HttpClient);

  requiredData$ = this.http.get<RequiredData>(`${this.baseUrl}/getRequiredData`)

  getItems(userSelections: UserSelections): Observable<Item[]> {
    userSelections = util.convertDatesToDateOnlyStrings(userSelections, ['productionPeriod'])
    const url = `${this.baseUrl}/GetItems?`;
    return this.http.put<Item[]>(url, userSelections);
  }

  getGridSettings(): Observable<FilterItem> {
    const url = `${this.baseUrl}/GetGridSettings`;
    return this.http.get<FilterItem>(url);
  }

  saveItems(actualTypeId: number, itemsToSave: Item[]): Observable<number> {
    const url = `${this.baseUrl}/SaveItems?actualTypeId=${actualTypeId}`;
    itemsToSave = util.convertDatesToDateOnlyStrings(itemsToSave, ['saveDate', 'date']);
    return this.http.put<number>(url, itemsToSave);
  }

  saveGridSettings(state: State): Observable<string> {
    const clonedState = util.deepCopy(state);
    clonedState.filter = null;  // don't save filter settings
    const stateJson: string = JSON.stringify(JSON.stringify(clonedState));

    const url = `${this.baseUrl}/SaveGridSettings`;
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
    return this.http.put<string>(url, stateJson, { headers });
  }

  exportItems(userSelections: UserSelections) {
    userSelections = util.convertDatesToDateOnlyStrings(userSelections, ['productionPeriod'])
    return this.http.post(`${this.baseUrl}/ExportItems?`, userSelections, { observe: 'response', responseType: 'blob' }).pipe(
      map(result => {
        const fileBlob = result.body;
        const fileName: string = result.body.type === "text/plain" ? "Error.txt" : 'CrudeActuals.xlsx';
        return { fileBlob, fileName };
      })
    );
  }

  setTneMeter(clickedItem: Item, tneMeterItems: Item[]): Observable<Item[]> {
    const url = `${this.baseUrl}/SetTneMeter`;

    clickedItem = util.convertDatesToDateOnlyStrings(clickedItem, ['saveDate', 'date']);
    tneMeterItems = util.convertDatesToDateOnlyStrings(tneMeterItems, ['saveDate', 'date']);

    const payload: SetTneMeterPayload = {
      clickedItem: clickedItem,
      tneMeterItems: tneMeterItems
    };

    return this.http.put<Item[]>(url, payload);
  }

  toggleTneMeter(clickedItem: Item, tneMeterItems: Item[]): Observable<Item[]> {
    const url = `${this.baseUrl}/ToggleTneMeter`;

    clickedItem = util.convertDatesToDateOnlyStrings(clickedItem, ['saveDate', 'date']);
    tneMeterItems = util.convertDatesToDateOnlyStrings(tneMeterItems, ['saveDate', 'date']);

    const payload: SetTneMeterPayload = {
      clickedItem: clickedItem,
      tneMeterItems: tneMeterItems
    };

    return this.http.put<Item[]>(url, payload);
  }

}
