import { XMLParser } from "fast-xml-parser";
import { RCIClient } from "../../lib/client";
import { differenceInDays, formatDateToMMddYYYY } from "../../lib/date";
import type { ResortsSearchResponse, ResponseHeader } from "../../type";
export class RCIResorts {
  private client: <TResponse>(init?: RequestInit) => Promise<TResponse | null>;
  constructor() {
    const baseURL = process.env.RCI_TRX_URL!;
    if (!baseURL) {
      throw new Error("Missing RCI Transaction URL");
    }
    this.client = RCIClient(baseURL);
  }

  async searchByRegion(
    credentials: {
      username: string;
      password: string;
    },
    queryParams: {
      regionCode: string;
      startDate: Date;
      endDate: Date;
      unitCode?: string | number;
    },
  ) {
    try {
      const searchStartDate = formatDateToMMddYYYY(queryParams.startDate, "/");
      const searchEndDate = formatDateToMMddYYYY(queryParams.endDate, "/");
      const stayLength = differenceInDays(
        queryParams.startDate,
        queryParams.endDate,
      );
      const response = await this.client<string>({
        method: "POST",
        body: `
        <requestEnvelope>
         	<requestHeader>
          		<controlData>
         			<clientName>XMLBusinessPartnerChannel</clientName>
         			<userID>${credentials.username}</userID>
         			<password>${credentials.password}</password>
          		</controlData>
          		<processData>
         			<operationName>quickSearch</operationName>
          		</processData>
         	</requestHeader>
         	<SearchRequest>
          		<startDate>${searchStartDate}</startDate>
          		<endDate>${searchEndDate}</endDate>
          		<lengthOfStay>${stayLength}</lengthOfStay>
          		<minUnitSize>${queryParams.unitCode ?? "H"}</minUnitSize>
          		<regionCode>${queryParams.regionCode}</regionCode>
         	</SearchRequest>
        </requestEnvelope>
        `,
      });
      if (!response) {
        return null;
      }
      const parser = new XMLParser();
      const xmlStringFixed = response.replace(
        /<resortId>(\d+)<\/resortId>/g,
        (_, digits) => `<resortId>'${digits}'</resortId>`,
      );
      const parsedResponse = parser.parse(xmlStringFixed) as {
        responseEnvelope: {
          responseHeader: ResponseHeader;
          SearchResponse: ResortsSearchResponse;
        };
      };
      return parsedResponse;
    } catch (err) {
      throw err instanceof Error ? err : new Error(String(err));
    }
  }

  async searchByResort(
    credentials: {
      username: string;
      password: string;
    },
    queryParams: {
      resortID: string;
      startDate: Date;
      endDate: Date;
      unitCode: string | number;
    },
  ) {
    try {
      const searchStartDate = formatDateToMMddYYYY(queryParams.startDate, "/");
      const searchEndDate = formatDateToMMddYYYY(queryParams.endDate, "/");
      const stayLength = differenceInDays(
        queryParams.startDate,
        queryParams.endDate,
      );
      const response = await this.client<string>({
        method: "POST",
        body: `
        <requestEnvelope>
         	<requestHeader>
          		<controlData>
         			<clientName>XMLBusinessPartnerChannel</clientName>
         			<userID>${credentials.username}</userID>
         			<password>${credentials.password}</password>
          		</controlData>
          		<processData>
         			<operationName>resortIdSearch</operationName>
          		</processData>
         	</requestHeader>
         	<SearchRequest>
          		<startDate>${searchStartDate}</startDate>
          		<endDate>${searchEndDate}</endDate>
          		<lengthOfStay>${stayLength}</lengthOfStay>
          		<minUnitSize>${queryParams.unitCode ?? "H"}</minUnitSize>
          		<resortId>${queryParams.resortID}</resortId>
         	</SearchRequest>
        </requestEnvelope>
        `,
      });
      if (!response) {
        return null;
      }
      const parser = new XMLParser();
      const parsedResponse = parser.parse(response) as {
        responseEnvelope: {
          responseHeader: ResponseHeader;
          SearchResponse: ResortsSearchResponse;
        };
      };
      return parsedResponse;
    } catch (err) {
      throw err instanceof Error ? err : new Error(String(err));
    }
  }
}
