import React, { useContext, useEffect, useMemo, useRef } from 'react';
import { useSelector } from 'react-redux';
import { SearchResultsRootState } from '../../store/search-results-store';
import { ClientPortalItinerary, ClientPortalItineraryItem, ClientPortalItineraryNode } from '@qite/tide-client';
import Spinner from '../spinner/spinner';
import SearchResultsConfigurationContext from '../../search-results-configuration-context';
import { getTranslations } from '../../../shared/utils/localization-util';
import { format } from 'date-fns';

const formatNodeDate = (date?: Date | string | null) => {
  if (!date) return '';

  try {
    return new Intl.DateTimeFormat('nl-BE', {
      weekday: 'long',
      day: '2-digit',
      month: '2-digit',
      year: 'numeric'
    }).format(new Date(date));
  } catch {
    return '';
  }
};

const escapeHtml = (value?: string | null) => {
  if (!value) return '';

  return value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
};

const getNodeDayRange = (node: ClientPortalItineraryNode) => {
  const startDay = Number(node.startDay ?? 0);
  const endDay = Number(node.endDay ?? startDay);

  return { startDay, endDay };
};

const getItemDuration = (item: ClientPortalItineraryItem) => {
  const duration = Number(item.productDuration ?? 0);

  return Number.isFinite(duration) && duration > 0 ? duration : 0;
};

const isAccommodationItem = (item: ClientPortalItineraryItem) => {
  return getItemDuration(item) > 1 && item.templateName?.toLowerCase().includes('hotel');
};

const getAccommodationName = (item: ClientPortalItineraryItem) => {
  return item.title || 'Onbekende accommodatie';
};

const getItemDeduplicationKey = (item: ClientPortalItineraryItem) => {
  const templateName = item.templateName?.toLowerCase();

  // if (templateName === 'hotel') {
  //   return [item.templateName, item.productCode, item.accommodationCode, item.regimeCode].filter(Boolean).join('|');
  // }

  // if (templateName === 'excursion') {
  //   return [item.templateName, item.productCode].filter(Boolean).join('|');
  // }

  return [item.templateName, item.productCode, item.title].filter(Boolean).join('|');
};

const getUniqueItems = (items: ClientPortalItineraryItem[] = []) => {
  const seen = new Set<string>();

  return items.filter((item) => {
    const key = getItemDeduplicationKey(item) || item.itemGuid;

    if (seen.has(key)) {
      return false;
    }

    seen.add(key);
    return true;
  });
};

const findAccommodationForDay = (nodes: ClientPortalItineraryNode[], currentDay: number) => {
  for (const node of nodes ?? []) {
    const { startDay } = getNodeDayRange(node);
    const uniqueItems = getUniqueItems(node.items ?? []);

    for (const item of uniqueItems) {
      if (!isAccommodationItem(item)) {
        continue;
      }

      const duration = getItemDuration(item);
      const accommodationEndDay = startDay + duration - 1;

      if (currentDay >= startDay && currentDay <= accommodationEndDay) {
        return item;
      }
    }
  }

  return null;
};

const buildItineraryHtml = (itinerary: ClientPortalItinerary | null, translations: any) => {
  if (!itinerary) {
    return `
      <div class="itinerary-shell">
        <div class="itinerary-empty">Geen reisroute beschikbaar.</div>
      </div>
    `;
  }

  const allNodes = itinerary.nodes ?? [];

  const nodesHtml = allNodes
    .map((node) => {
      const { startDay } = getNodeDayRange(node);
      const day = node.startDate ? format(node.startDate, 'd') : null;
      const month = node.startDate ? format(node.startDate, 'MMM') : null;
      const uniqueItems = getUniqueItems(node.items ?? []);

      const hasItems = uniqueItems.length > 0;
      const hasAccommodationInCurrentNode = uniqueItems.some(isAccommodationItem);
      const activeAccommodation = findAccommodationForDay(allNodes, startDay);

      const accommodationBanner =
        !hasAccommodationInCurrentNode && activeAccommodation
          ? `
            <div class="itinerary-node__accommodation-banner">
              Accommodatie voor deze dag: <strong>${escapeHtml(getAccommodationName(activeAccommodation))}</strong>
            </div>
          `
          : '';

      const itemsHtml = hasItems
        ? uniqueItems
            .map(
              (item) => `
                <article class="itinerary-item" data-template="${escapeHtml(item.templateName)}">
                  ${item.contents ?? ''}
                </article>
              `
            )
            .join('')
        : `<div class="itinerary-node__empty">${translations.ITINERARY.NO_ITEMS}</div>`;

      return `
        <section class="itinerary-node">
          <header class="itinerary-node__header">
            
          <div class="itinerary-node__day">
            <p class="itinerary-node__day-day">${day}</p>
            <p class="itinerary-node__day-month">${month}</p>
          </div>

            <div>
              <h2 class="itinerary-node__title">${escapeHtml(node.title)}</h2>
            </div>
          </header>

          <div class="itinerary-node__content">
            ${accommodationBanner}
            ${itemsHtml}
          </div>
        </section>
      `;
    })
    .join('');

  const defaultItemsHtml =
    itinerary.defaultItems && itinerary.defaultItems.length > 0
      ? `
        <section class="itinerary-default-items">
          <h2 class="itinerary-default-items__title">Algemene info</h2>
          ${getUniqueItems(itinerary.defaultItems)
            .map(
              (item) => `
                <article class="itinerary-item" data-template="${escapeHtml(item.templateName)}">
                  ${item.contents ?? ''}
                </article>
              `
            )
            .join('')}
        </section>
      `
      : '';

  return `
    <div class="itinerary-shell">
      ${itinerary.title ? `<header class="itinerary-shell__header"><h1 class="itinerary-shell__title">${escapeHtml(itinerary.title)}</h1></header>` : ''}

      <div class="itinerary-shell__content">
        ${nodesHtml}
        ${defaultItemsHtml}
      </div>
    </div>
  `;
};

interface FullItineraryProps {
  isLoading: boolean;
}

const FullItinerary: React.FC<FullItineraryProps> = ({ isLoading }) => {
  const { itinerary } = useSelector((state: SearchResultsRootState) => state.searchResults);
  const context = useContext(SearchResultsConfigurationContext);
  const translations = getTranslations(context?.languageCode ?? 'en-GB');

  const hostRef = useRef<HTMLDivElement | null>(null);
  const shadowRootRef = useRef<ShadowRoot | null>(null);

  const html = useMemo(() => buildItineraryHtml(itinerary as ClientPortalItinerary | null, translations), [itinerary, translations]);

  useEffect(() => {
    if (isLoading) {
      return;
    }

    const host = hostRef.current;

    if (!host) {
      return;
    }

    const shadowRoot = host.shadowRoot ?? host.attachShadow({ mode: 'open' });

    shadowRootRef.current = shadowRoot;

    shadowRoot.innerHTML = `
      <style>
        :host {
          all: initial;
          display: block;
          width: 100%;
        }

        *,
        *::before,
        *::after {
          box-sizing: border-box;
        }

        .itinerary-shell {
          width: 100%;
          margin: 0 auto;
          font-family: 'Outfit', sans-serif;
          color: #222;
        }

        .itinerary-shell__header {
          margin-bottom: 24px;
        }

        .itinerary-shell__title {
          margin: 0;
          font-size: 32px;
          line-height: 1.2;
        }

        .itinerary-shell__content {
          display: grid;
          gap: 24px;
        }

        .itinerary-node {
          border: 1px solid #e5e7eb;
          border-radius: 16px;
          overflow: hidden;
          background: #fff;
          box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
        }

        .itinerary-node__header {
          display: flex;
          gap: 16px;
          align-items: center;
          border-bottom: 1px solid #eef0f2;
          background: #fafafa;
        }

        .itinerary-node__day {
          flex: 50px 0 0;
          display: flex;
          flex-flow: column;
          align-items: center;
          justify-content: center;
          background: #1f9470;
          color: white;
          border: 1.5px solid var(--tide-booking-color-secondary);
        }

        .itinerary-node__day-month {
          margin: 0px;
        }

        .itinerary-node__day-day {
          margin: 0px;
          font-weight: var(--tide-booking-search-results-label-date-month-font-weight);
          color: var(--tide-booking-search-results-label-date-month-color);
          font-size: 24px;
        }

        .itinerary-node__title {
          margin: 0;
          font-size: 22px;
          line-height: 1.25;
        }

        .itinerary-node__content {
          display: grid;
          gap: 20px;
          padding: 20px;
        }

        .itinerary-node__accommodation-banner {
          padding: 12px 16px;
          border: 1px solid #dbeafe;
          border-radius: 12px;
          background: #eff6ff;
          color: #1e3a8a;
          font-size: 14px;
          line-height: 1.4;
        }

        .itinerary-item {
          display: block;
          border-radius: 12px;
          overflow: hidden;
          background: #fff;
        }

        .itinerary-node__empty,
        .itinerary-empty {
          padding: 20px;
          border: 1px dashed #d1d5db;
          border-radius: 12px;
          color: #6b7280;
          background: #fafafa;
        }

        .itinerary-default-items {
          border: 1px solid #e5e7eb;
          border-radius: 16px;
          padding: 20px;
          background: #fff;
          box-shadow: 0 2px 10px rgba(0, 0, 0, 0.04);
        }

        .itinerary-default-items__title {
          margin: 0 0 16px;
          font-size: 22px;
        }

        @media (max-width: 768px) {
          .itinerary-shell {
            padding: 16px;
          }
        }

        ${itinerary?.styleSheetBody ?? ''}
      </style>

      ${html}
    `;
  }, [html, itinerary?.styleSheetBody, isLoading]);

  return (
    <>
      {isLoading && <Spinner label={translations.SRP.LOADING_ITINERARY} />}
      <div ref={hostRef} style={{ display: isLoading ? 'none' : 'block' }} />
    </>
  );
};

export default FullItinerary;
