package com.fractalite.amad_ndc.convertersRS;


import com.amadeus.travelManagement.amadeus.xml._2010._06.travel_orderviewrs_v1.*;
import com.amadeus.travelManagement.amadeus.xml._2010._06.travel_orderviewrs_v1.AMATravelOrderViewRS.*;
import com.amadeus.travelManagement.amadeus.xml._2010._06.travel_orderviewrs_v1.OrderType;
import com.amadeus.travelManagement.amadeus.xml._2010._06.travel_orderviewrs_v1.PriceType;
import com.amadeus.travelManagement.amadeus.xml._2010._06.travel_orderviewrs_v1.ResponseType.*;
import com.fractalite.mercure.data.model.bo.*;
import com.fractalite.mercure.data.model.person.Beneficiary;
import com.fractalite.mercure.data.model.person.LegalPerson;
import com.fractalite.mercure.data.model.person.NaturalPerson;
import com.fractalite.mercure.data.model.person.Person;
import com.fractalite.mercure.data.model.product.Itinerary;
import com.fractalite.mercure.data.model.product.SpaceTimePoint;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class TravelOrderCreateRS {

    private static final DateTimeFormatter TIME_FMT = DateTimeFormatter.ofPattern("HH:mm");

    /**
     * Maps AMA_TravelOrderViewRS XML to the Mercure Order model.
     *
     * Strategy:
     *   - Amadeus returns 1 OrderItem per passenger (PAX1, PAX2, PAX3)
     *   - Mercure has 1 Item per passenger type group (ADT group, CHD group)
     *   - We group Amadeus OrderItems by PTC and match them to Mercure Items via tags
     */
    public Order buildOrderView(Order order, AMATravelOrderViewRS amaResponse) {
        if (amaResponse == null || amaResponse.getResponse() == null) return order;

        ResponseType response = amaResponse.getResponse();
        DataListsType dataLists = response.getDataLists();

        if (response.getOrder() == null || response.getOrder().isEmpty()) return order;
        OrderType sourceOrder = response.getOrder().get(0);

        // ── 1. PNR / Order ref ──────────────────────────────────────────────────
        String pnr = sourceOrder.getOrderID();
        if (sourceOrder.getBookingRef() != null) {
            pnr = sourceOrder.getBookingRef().stream()
                    .filter(b -> b.getBookingEntity() != null
                            && b.getBookingEntity().getCarrier() != null)
                    .map(BookingRefType::getBookingID)
                    .findFirst()
                    .orElse(sourceOrder.getOrderID());
        }
        order.setRef(pnr);
        order.setNumber(pnr);
        order.setStatus(OrderStatus.Preorder);

        // ── 2. Build PaxID → PTC map from DataLists/PaxList ─────────────────────
        // e.g. { "PAX1" → "ADT", "PAX2" → "ADT", "PAX3" → "CHD" }
        Map<String, String> paxIdToPtc = new LinkedHashMap<>();
        if (dataLists != null && dataLists.getPaxList() != null) {
            for (PaxType pax : dataLists.getPaxList().getPax()) {
                paxIdToPtc.put(pax.getPaxID(), pax.getPTC());
            }
        }

        // ── 3. Group Amadeus OrderItems by PTC ──────────────────────────────────
        // Extract PaxID from OrderItemID pattern: "uuid_1APAX_PAX1" → "PAX1"
        // e.g. { "ADT" → [orderItem_PAX1, orderItem_PAX2], "CHD" → [orderItem_PAX3] }
        Map<String, List<OrderItemType>> orderItemsByPtc = new LinkedHashMap<>();
        for (OrderItemType orderItem : sourceOrder.getOrderItem()) {
            String orderItemId = orderItem.getOrderItemID();
            // Extract last segment: "...PAX_PAX1" → "PAX1"
            String paxId = orderItemId.substring(orderItemId.lastIndexOf("_") + 1);
            String ptc = paxIdToPtc.getOrDefault(paxId, "ADT");
            orderItemsByPtc.computeIfAbsent(ptc, k -> new ArrayList<>()).add(orderItem);
        }

        // ── 4. Match each Mercure Item to its PTC group via tags ─────────────────
        // item.getTags() format: ";PAX1:ADT;PAX2:ADT" or ";PAX3:CHD"
        // split(";")[1] → "PAX1:ADT", split(":")[0] → "PAX1" (a PaxID)
        for (Item item : order.getItems()) {
            try {
                String[] tagParts = item.getTags().split(";");
                if (tagParts.length < 2) continue;

                // First paxId in the tag → look up PTC
                String firstPaxId = tagParts[1].split(":")[0]; // e.g. "PAX1" or "PAX3"
                String ptc = paxIdToPtc.getOrDefault(firstPaxId, extractPtcFromTag(tagParts[1]));

                List<OrderItemType> matchedOrderItems =
                        orderItemsByPtc.getOrDefault(ptc, Collections.emptyList());

                if (matchedOrderItems.isEmpty()) continue;

                item.setRef(pnr);
                item.setNumber(sourceOrder.getOrderID());
                item.setStatus(OrderStatus.Preorder);

                // Price: use first OrderItem of the group (same PTC = same unit fare)
                OrderItemType firstOrderItem = matchedOrderItems.get(0);
                if (firstOrderItem.getPrice() != null) {
                    buildPricesItem(matchedOrderItems, item);
                }

            } catch (Exception e) {
                System.err.println("Error processing item tags: " + item.getTags() + " → " + e.getMessage());
            }
        }

        return order;
    }

    // ── Price Builder ────────────────────────────────────────────────────────────
    private void buildPricesItem(List<OrderItemType> orderItems, Item item) {
        float totalBase  = 0f;
        float totalTax   = 0f;
        float totalTotal = 0f;
        String currency  = "EUR"; // fallback

        for (OrderItemType orderItem : orderItems) {
            PriceType priceRes = orderItem.getPrice();
            if (priceRes == null) continue;

            // BASE
            if (priceRes.getBaseAmount() != null) {
                totalBase += priceRes.getBaseAmount().getValue().floatValue();
                currency = priceRes.getBaseAmount().getCurCode();
            }

            // TAX
            if (priceRes.getTaxSummary() != null && !priceRes.getTaxSummary().isEmpty()
                    && priceRes.getTaxSummary().get(0).getTotalTaxAmount() != null) {
                totalTax += priceRes.getTaxSummary().get(0).getTotalTaxAmount().getValue().floatValue();
            }

            // TOTAL
            if (priceRes.getTotalAmount() != null) {
                totalTotal += priceRes.getTotalAmount().getValue().floatValue();
                currency = priceRes.getTotalAmount().getCurCode();
            }
        }

        List<Price> prices = new ArrayList<>();

        Price basePrice = new Price();
        basePrice.setCurrency(Currency.getInstance(currency));
        basePrice.setValue(totalBase);
        basePrice.setScope(PriceScope.PURCHASE_TOTAL_BASE);
        prices.add(basePrice);

        Price taxPrice = new Price();
        taxPrice.setCurrency(Currency.getInstance(currency));
        taxPrice.setValue(totalTax);
        taxPrice.setScope(PriceScope.TAX_TOTAL);
        prices.add(taxPrice);

        Price totalPrice = new Price();
        totalPrice.setCurrency(Currency.getInstance(currency));
        totalPrice.setValue(totalTotal);
        totalPrice.setScope(PriceScope.TOTAL);
        prices.add(totalPrice);

        item.setPrices(prices);
    }
    private void buildPricesItemOLD(PriceType priceRes, Item item) {
        List<Price> prices = new ArrayList<>();

        // Total
        if (priceRes.getTotalAmount() != null) {
            Price totalPrice = new Price();
            totalPrice.setCurrency(Currency.getInstance(priceRes.getTotalAmount().getCurCode()));
            totalPrice.setValue(priceRes.getTotalAmount().getValue().floatValue());
            totalPrice.setScope(PriceScope.TOTAL);
            prices.add(totalPrice);
        }

        // Base
        if (priceRes.getBaseAmount() != null) {
            Price basePrice = new Price();
            basePrice.setCurrency(Currency.getInstance(priceRes.getBaseAmount().getCurCode()));
            basePrice.setValue(priceRes.getBaseAmount().getValue().floatValue());
            basePrice.setScope(PriceScope.BASE);
            prices.add(basePrice);
        }

        // Tax
        if (priceRes.getTaxSummary() != null && !priceRes.getTaxSummary().isEmpty()) {
            Price taxPrice = new Price();
            taxPrice.setCurrency(Currency.getInstance(
                    priceRes.getTaxSummary().get(0).getTotalTaxAmount().getCurCode()));
            taxPrice.setValue(
                    priceRes.getTaxSummary().get(0).getTotalTaxAmount().getValue().floatValue());
            taxPrice.setScope(PriceScope.TAX_TOTAL);
            prices.add(taxPrice);
        }

        item.setPrices(prices);
    }

    // ── Helpers ──────────────────────────────────────────────────────────────────

    /**
     * Fallback: extract PTC from tag string like "PAX1:ADT" → "ADT"
     * Used when PaxID is not found in paxIdToPtc map.
     */
    private String extractPtcFromTag(String tag) {
        // tag format: "PAX1:ADT"
        String[] parts = tag.split(":");
        if (parts.length >= 2) {
            return extractPaxType(parts[1]);
        }
        return "ADT";
    }

    private String extractPaxType(String ref) {
        if (ref.contains("ADT")) return "ADT";
        if (ref.contains("CHD")) return "CHD";
        if (ref.contains("ENF") || ref.contains("INF")) return "INF";
        return "ADT";
    }

    private Optional<LocalDateTime> parseDateTime(String r) {
        try {
            return Optional.of(LocalDateTime.parse(r, DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        } catch (Exception e) {
            return Optional.empty();
        }
    }
}