package com.fractalite.amad_ndc.convertersRS;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Currency;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;

import com.amadeus.xml.fmptbr_24_1_1a.FareMasterPricerTravelBoardSearchReply;
import com.amadeus.xml.fmptbr_24_1_1a.MonetaryInformationDetailsType277475C;
import com.amadeus.xml.fmptbr_24_1_1a.MonetaryInformationType204470S;
import com.amadeus.xml.fmptbr_24_1_1a.FareMasterPricerTravelBoardSearchReply.FlightIndex;
import com.amadeus.xml.fmptbr_24_1_1a.FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights.FlightDetails;
import com.amadeus.xml.fmptbr_24_1_1a.FareMasterPricerTravelBoardSearchReply.Recommendation;
import com.amadeus.xml.fmptbr_24_1_1a.ProposedSegmentDetailsType;
import com.amadeus.xml.fmptbr_24_1_1a.ReferenceInfoType;
import com.amadeus.xml.fmptbr_24_1_1a.TravelProductType;
import com.fractalite.mercure.dto.product.Rate;
import com.fractalite.mercure.data.model.bo.Tax;
import com.fractalite.mercure.data.model.product.*;

@Component
public class Fare_MasterPricerTravelBoardSearchRS {

private static final DateTimeFormatter TIME_FMT = DateTimeFormatter.ofPattern("HHmm");
	
	public  List<Product> buildProducts(FareMasterPricerTravelBoardSearchReply reply) {
		String currency=reply.getConversionRate().getConversionRateDetail().get(0).getCurrency();
		
		Product product = new Product();
		
		  ProductType productType = new ProductType();
          productType.setProductTypeId(1L);
          productType.setCode("ndc");
          product.setProducType(productType);
       //   product.setReference(offer.getOfferID());
      //    product.setSupplier(buildSupplier(offer));
          Map<Integer, FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights> flightMap = indexFlights(reply);

          for (Recommendation rec : reply.getRecommendation()) {

              Itinerary itinerary = buildItinerary(rec, flightMap);
              List<Product> products= buildProducts( rec,itinerary,currency);
          }


		return null;
		
	}
	
	
	private List<Product> buildProducts(Recommendation rec,Itinerary itinerary,String currency) {

		Product product = new Product();

	    product.setName(
	            rec.getItemNumber()
	               .getItemNumberId()
	               .getNumber()
	    );

	    MonetaryInformationType204470S priceInfo = rec.getRecPriceInfo();
	    MonetaryInformationDetailsType277475C total = priceInfo.getMonetaryDetail().get(0);
	    MonetaryInformationDetailsType277475C tax   = priceInfo.getMonetaryDetail().get(1);
	    product.setRateGroups(buildRateGroups(  rec,
			         itinerary , currency));
	    

	   

	    return List.of(product);
	}
	
	 private Itinerary buildItinerary(
	            Recommendation rec,
	            Map<Integer, FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights> flightMap) {

	        Itinerary itinerary = new Itinerary();
	        itinerary.setName(
	                rec.getItemNumber()
	                   .getItemNumberId()
	                   .getNumber()
	        );

	        int priority = 1;

	        for (ReferenceInfoType segRef : rec.getSegmentFlightRef()) {
	            int refNumber = segRef.getReferencingDetail().stream()
	                    .filter(r -> "S".equals(r.getRefQualifier()))
	                    .findFirst()
	                    .map(r -> r.getRefNumber().intValue())
	                    .orElseThrow(() ->
	                        new IllegalStateException("Missing segment reference")
	                    );

	            FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights gof = flightMap.get(refNumber);
	            SpaceTimePoint stp = buildSpaceTimePoint(gof, priority++);

	            itinerary.getSpaceTimePoints().add(stp);
	        }

	        buildItineraryTags(itinerary);
	        return itinerary;
	    }
	
	  
	  private Map<Integer, FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights> indexFlights(
		        FareMasterPricerTravelBoardSearchReply xml) {

		    Map<Integer, FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights> map = new HashMap<>();

		    for (FlightIndex fi : xml.getFlightIndex()) {
		        for (FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights gof : fi.getGroupOfFlights()) {

		            for (ProposedSegmentDetailsType fp :
		                    gof.getPropFlightGrDetail().getFlightProposal()) {

		                if ("S".equals(fp.getUnitQualifier())) {
		                    map.put(
		                        Integer.parseInt(fp.getRef()),
		                        gof
		                    );
		                }
		            }
		        }
		    }
		    return map;
		}
	  
	  
	  private SpaceTimePoint buildSpaceTimePoint(
			  FareMasterPricerTravelBoardSearchReply.FlightIndex.GroupOfFlights gof,
		        int priority) {

		    FlightDetails fd = gof.getFlightDetails().get(0);
		    TravelProductType fi = fd.getFlightInformation();

		    SpaceTimePoint stp = new SpaceTimePoint();
		    stp.setPriority(priority);

		    stp.setDfrom(
		            fi.getLocation().get(0).getLocationId()
		            + ":T1"
		    );
		    stp.setDto(
		            fi.getLocation().get(1).getLocationId()
		            + ":T1"
		    );

		    stp.setFromDate(formatDate(
		            fi.getProductDateTime().getDateOfDeparture()
		    ));
		    stp.setFromTime(formatTime(
		            fi.getProductDateTime().getTimeOfDeparture()
		    ));

		    stp.setToDate(formatDate(
		            fi.getProductDateTime().getDateOfArrival()
		    ));
		    stp.setToTime(formatTime(
		            fi.getProductDateTime().getTimeOfArrival()
		    ));

		    stp.setDuration(
		    		computeDuration(
		    		        fi.getProductDateTime().getTimeOfDeparture(),
		    		        fi.getProductDateTime().getTimeOfArrival()
		    		    ));

		    stp.setTags(buildSegmentTags(fi));
		    return stp;
		}

	  
	  private Date formatDate(String amadeusDate) {
		    // amadeusDate example: "251226" → 2025-12-26
		    SimpleDateFormat amadeusFormat = new SimpleDateFormat("yyMMdd");
		    amadeusFormat.setLenient(false);

		    try {
		        return amadeusFormat.parse(amadeusDate);
		    } catch (Exception e) {
		        throw new IllegalArgumentException(
		            "Invalid Amadeus date: " + amadeusDate, e
		        );
		    }
		}

		private String formatTime(String t) {
		    return t.substring(0,2) + ":" + t.substring(2,4);
		}
		
		private LocalTime parseTime(String time) {
		    return LocalTime.parse(time, TIME_FMT);
		}
		private String computeDuration(
		        String depTime,
		        String arrTime) {

		    LocalTime departure = parseTime(depTime);
		    LocalTime arrival   = parseTime(arrTime);

		    Duration duration = Duration.between(departure, arrival);

		    // Handle overnight flights (arrival after midnight)
		    if (duration.isNegative()) {
		        duration = duration.plusHours(24);
		    }

		    return duration.toString(); // ISO-8601 → PT#H#M
		}
		
		
		private List<String> buildSegmentTags(TravelProductType fi) {

		    List<String> tags = new ArrayList<>();

		    tags.add("ECONOMY:" + fi.getClass());
		    tags.add(
		        fi.getCompanyId().getMarketingCarrier()
		        + fi.getFlightOrtrainNumber()
		    );
		    tags.add("equipment:" +
		        fi.getProductDetail().getEquipmentType()
		    );

		    return tags;
		}
		  private void buildItineraryTags(Itinerary itinerary) {
		        itinerary.getTags().add("ECONOMY");
		        itinerary.getTags().add("SEGMENTS:" + itinerary.getSpaceTimePoints().size());
		    }
		  
		  private List<RateGroup> buildRateGroups(
			        Recommendation rec,
			        Itinerary itinerary ,String currency) {
			  RateGroup rateGroup = new RateGroup();
			    rateGroup.setQuantity(0);

			    RateDetail rate = new RateDetail();			    
			    rate.setQuantity(1);
			    rate.setMin(1);
			    rate.setMax(2);

			    // ---- PRICE ----
			    MonetaryInformationType204470S priceInfo = rec.getRecPriceInfo();

			    MonetaryInformationDetailsType277475C total = priceInfo.getMonetaryDetail().stream()
			            .filter(m -> "TOTAL".equals(m.getAmountType()))
			            .findFirst()
			            .orElse(priceInfo.getMonetaryDetail().get(0));

			    MonetaryInformationDetailsType277475C tax = priceInfo.getMonetaryDetail().stream()
			            .filter(m -> "TAX".equals(m.getAmountType()))
			            .findFirst()
			            .orElse(priceInfo.getMonetaryDetail().get(1));

			    rate.setPrice(total.getAmount().floatValue());
			    rate.setPurchasePrice(rate.getPrice());
			    rate.setTaxes(null);

			    if (tax != null) {
			    	Tax ratTax = new Tax();
			    	ratTax.setCode("TOTAL");
			    	ratTax.setAmount((new BigDecimal(tax.getAmountType())).floatValue());
			    	ratTax.setCurrency(Currency.getInstance(currency));
			        rate.getTaxes().add(ratTax);
			    }

			    // ---- ITINERARY ----
			    rate.getItinerary().add(itinerary);

			    rateGroup.getRates().add(rate);

			    return List.of(rateGroup);
			}

}
