import React, { Component } from 'react';
import { Briefcase, Calendar, User, CreditCard, 
  CheckCircle, HelpCircle, CircleCheckBig, MapPin,
} from 'lucide-react';
import { __, sprintf } from '@wordpress/i18n';
import ServiceStep from './components/ServiceStep.jsx';
import DateTimeStep from './components/DateTimeStep.jsx';
import InfoStep from './components/InfoStep.jsx';
import PaymentStep from './components/PaymentStep.jsx';
import ConfirmationStep from './components/ConfirmationStep.jsx';
import { useBookingStore, updateInput } from '../FormContext';
import currencies from '../currencies.json';

const ProLocationStep = window.BookifyPro && window.BookifyPro.Light ? window.BookifyPro.Light.LocationStep : null;
const ProStaffStep = window.BookifyPro && window.BookifyPro.Light ? window.BookifyPro.Light.StaffStep : null;

const buildCategorized = (categories = [], services = []) => {
  if (!Array.isArray(categories) || !Array.isArray(services)) return [];
  return categories
    .map((category) => ({
      name: category.category_name,
      id: category.id,
      services: services
        .filter((service) => service.service_category === category.id)
        .map((service) => ({
          id: service.id,
          name: service.service_name,
          category: category.category_name,
          price: Number(service.service_price) || 0,
          duration: service.service_duration || '',
        })),
    }))
    .filter((category) => category.services.length > 0);
};

const getInitialStep = (showLocationStep, showServiceStep, showStaffStep) => {
  if (showLocationStep) return 'location';
  if (showServiceStep) return 'service';
  if (showStaffStep) return 'staff';
  return 'date_time';
};

const getSteps = (showLocationStep, showServiceStep, showStaffStep) => {
  const baseSteps = [
    showLocationStep
      ? {
          id: 'location',
          label: wp.hooks.applyFilters('bookify_location_tab_label', __('Location', 'bookify')),
          title: __('Location', 'bookify'),
          icon: MapPin,
        }
      : null,
    showServiceStep
      ? { id: 'service', label: wp.hooks.applyFilters('bookify_service_tab_label', __('Service', 'bookify')), title: __('Service', 'bookify'), icon: Briefcase }
      : null,
    showStaffStep && ProStaffStep
      ? { id: 'staff', label: wp.hooks.applyFilters('bookify_staff_tab_label', __('Staff', 'bookify')), title: __('Staff', 'bookify'), icon: User }
      : null,
    { id: 'date_time', label: wp.hooks.applyFilters('bookify_datetime_tab_label', __('Date & Time', 'bookify')), title: __('Date & Time', 'bookify'), icon: Calendar },
    { id: 'information', label: wp.hooks.applyFilters('bookify_userinfo_tab_label', __('Your Information', 'bookify')), title: __('Your Information', 'bookify'), icon: User },
    { id: 'payments', label: wp.hooks.applyFilters('bookify_payment_tab_label', __('Payments', 'bookify')), title: __('Payments', 'bookify'), icon: CreditCard },
    { id: 'confirmation', label: wp.hooks.applyFilters('bookify_confirmation_tab_label', __('Confirmation', 'bookify')), title: wp.hooks.applyFilters('bookify_confirmation_section_title', __('Confirmation', 'bookify')), icon: CheckCircle },
  ];
  return baseSteps.filter(Boolean);
};

class LightFrontendAppClass extends Component {
  constructor(props) {
    super(props);
    const showLocationStep = wpbApp?.HideLocations !== 'true' && wpbApp?.locationsCount > 0 && ProLocationStep;
    const showServiceStep = wpbApp?.HideServices !== 'true';
    const showStaffStep = wpbApp?.HideStaffs !== 'true' && ProStaffStep;
    this.state = {
      currentStep: getInitialStep(showLocationStep, showServiceStep, showStaffStep),
    };
    this.prevLocationServiceRef = { locationId: props.state?.locationId, serviceId: props.state?.serviceId };
  }

  componentDidMount() {
    this.initialise();
  }

  componentDidUpdate(prevProps) {
    const { state } = this.props;
    const prev = this.prevLocationServiceRef;
    const locationChanged = prev.locationId !== state.locationId;
    const serviceChanged = prev.serviceId !== state.serviceId;
    this.prevLocationServiceRef = { locationId: state.locationId, serviceId: state.serviceId };
    if (!locationChanged && !serviceChanged) return;

    const resolvedServiceId = wpbApp?.HideServices === 'true' && state.locationId
      ? (Array.isArray(wpbApp.Services) ? wpbApp.Services[0] : wpbApp.Services)
      : null;
    let serviceName = '';
    if (resolvedServiceId && Array.isArray(state.categorizedServices) && state.categorizedServices.length > 0) {
      const flat = state.categorizedServices.flatMap((cat) => cat.services || []);
      const match = flat.find((s) => `${s.id}` === `${resolvedServiceId}`);
      if (match) serviceName = match.name || '';
    }
    updateInput({
      staffId: null,
      staffName: '',
      daysOpen: {},
      specialDate: {},
      holidays: [],
      date: null,
      slot: [],
      slots: [],
      staffsByServices: [],
      staffStopRerendering: false,
      ...(wpbApp?.HideServices === 'true' && resolvedServiceId
        ? { serviceId: resolvedServiceId, serviceName: serviceName || state.serviceName || '' }
        : {}),
    });
  }

  resolveServiceFromWp = () => {
    const raw = wpbApp?.Services;
    if (!raw) return null;
    return Array.isArray(raw) ? raw[0] : raw;
  };

  fetchSettings = async () => {
    const { updateInput } = this.props;
    try {
      const res = await fetch(`${wpbApp.root}bookify/frontend/v1/settings`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          'X-WP-Nonce': wpbApp.nonce,
        },
      });
      const data = await res.json();
      const matchedCurrency = Object.values(currencies || {}).find(
        (eachCurrency) => eachCurrency.code === data.general.DefaultGeneralCurrencies
      );

      updateInput({
        currencySymbol: matchedCurrency?.symbol_native || '',
        currencyCode: matchedCurrency?.code || 'USD',
        weekStartsOn: data.general.DefaultWeekStartOn,
        toggleLimitedBooking: data.general.DefaultPriorToBooking,
        limitedBookingMonths: data.general.PriorTimeToBooking,
        timeFormat: data.general.DefaultTimeFormat,
        slotsTimezone: data.general.slotsTimezone,
        supportLinkText: data.general.supportLinkText,
        supportLinkUrl: data.general.supportLinkUrl,
        showFormSupportLink: data.general.showFormSupportLink,
        gcalForCustomer: data.integration.gcalForCustomer,
        ocalForCustomer: data.integration.ocalForCustomer,
        zoomToggle: data.integration.ZoomToggle,
      });
    } catch (error) {
      console.error('Error fetching settings:', error);
    }
  };

  fetchLocations = async () => {
    const { updateInput } = this.props;
    try {
      const res = await fetch(`${wpbApp.root}bookify/v1/get-locations`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          'X-WP-Nonce': wpbApp.nonce,
          Locations: wpbApp.Locations,
        },
      });
      const data = await res.json();
      updateInput({ locations: data.locations || [] });
    } catch (error) {
      console.error('Error fetching locations:', error);
    }
  };

  fetchServicesByHiddenLocation = async () => {
    const { state, updateInput } = this.props;
    const pickFirst = (val) => (Array.isArray(val) ? val[0] : val);
    const hiddenLocation = pickFirst(wpbApp?.Locations);
    if (!hiddenLocation) return;

    try {
      const res = await fetch(`${wpbApp.root}bookify/frontend/v1/get-services-by-location`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-WP-Nonce': wpbApp.nonce,
        },
        body: JSON.stringify({
          location_id: hiddenLocation,
          services: wpbApp.Services,
        }),
      });

      const data = await res.json();
      const categorizedServices =
        (data.services || []).map((category) => ({
          name: category.category_name,
          services: (category.services || []).map((service) => ({
            id: service.id,
            name: service.service_name || service.name,
            category: category.category_name,
            price: Number(service.service_price ?? service.price ?? 0),
            duration: service.service_duration || service.duration || '',
            image: service.service_img || service.image || '',
          })),
        })) || [];

      const resolvedId = Array.isArray(wpbApp?.Services) ? wpbApp.Services[0] : wpbApp?.Services;
      const flatServices = categorizedServices.flatMap((cat) => cat.services || []);
      const match = resolvedId ? flatServices.find((s) => `${s.id}` === `${resolvedId}`) : null;
      updateInput({
        locationId: hiddenLocation,
        categorizedServices,
        serviceByLocaionLoading: false,
        serviceStopRerendering: true,
        ...(wpbApp?.HideServices === 'true' && resolvedId
          ? {
              serviceId: resolvedId,
              serviceName: match?.name || state.serviceName || '',
            }
          : {}),
      });
    } catch (error) {
      console.error('Error fetching services by hidden location:', error);
      updateInput({ serviceByLocaionLoading: false });
    }
  };

  fetchServices = async () => {
    const { state, updateInput } = this.props;
    try {
      const res = await fetch(`${wpbApp.root}bookify/frontend/v1/get-services`, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
          'X-WP-Nonce': wpbApp.nonce,
          Services: wpbApp.Services,
        },
      });
      const data = await res.json();
      const categorizedServices = buildCategorized(data.categories, data.services);

      const resolvedServiceId = this.resolveServiceFromWp();
      const matchedService = (data.services || []).find(
        (svc) => `${svc.id}` === `${resolvedServiceId}` || `${svc.service_id}` === `${resolvedServiceId}`
      );
      const resolvedServiceName =
        matchedService?.service_name || matchedService?.name || state.serviceName || '';
      const resolvedServicePrice = Number(
        matchedService?.service_price ?? matchedService?.price ?? state.servicePrice ?? 0
      );

      updateInput({
        categories: data.categories || [],
        services: data.services || [],
        categorizedServices,
        serviceId: wpbApp?.HideServices === 'true' && resolvedServiceId ? resolvedServiceId : state.serviceId,
        serviceName: wpbApp?.HideServices === 'true' && resolvedServiceName ? resolvedServiceName : state.serviceName,
        servicePrice:
          wpbApp?.HideServices === 'true' && resolvedServiceId ? resolvedServicePrice : state.servicePrice,
        serviceStopRerendering: true,
      });
    } catch (error) {
      console.error('Error fetching services:', error);
    }
  };

  initialise = async () => {
    const { state, updateInput } = this.props;
    const showLocationStep = wpbApp?.HideLocations !== 'true' && wpbApp?.locationsCount > 0 && !!ProLocationStep;

    updateInput({ dataLoading: true });

    try {
      await this.fetchSettings();

      const hideLocations = wpbApp?.HideLocations === 'true';
      const hideServices = wpbApp?.HideServices === 'true';
      const hasPresetLocation = hideLocations && (Array.isArray(wpbApp?.Locations) ? wpbApp.Locations.length > 0 : !!wpbApp?.Locations);

      if (showLocationStep) {
        await this.fetchLocations();
      } else if (hasPresetLocation) {
        const locationId = Array.isArray(wpbApp?.Locations) ? wpbApp.Locations[0] : wpbApp?.Locations || null;
        const resolvedServiceId = hideServices ? (Array.isArray(wpbApp?.Services) ? wpbApp.Services[0] : wpbApp?.Services ?? null) : null;
        updateInput({
          serviceStopRerendering: hideServices,
          serviceByLocaionLoading: !hideServices,
          categorizedServices: [],
          categories: [],
          services: [],
          locationId,
          ...(hideServices && resolvedServiceId != null
            ? { serviceId: resolvedServiceId, serviceName: state.serviceName || '' }
            : {}),
        });
        if (!hideServices) {
          await this.fetchServicesByHiddenLocation();
        }
      } else {
        await this.fetchServices();
      }
    } catch (error) {
      console.error('Error initialising booking form:', error);
    } finally {
      updateInput({ dataLoading: false });
    }
  };

  handleNext = () => {
    const showLocationStep = wpbApp?.HideLocations !== 'true' && wpbApp?.locationsCount > 0 && ProLocationStep;
    const showServiceStep = wpbApp?.HideServices !== 'true';
    const showStaffStep = wpbApp?.HideStaffs !== 'true' && ProStaffStep;
    const steps = getSteps(showLocationStep, showServiceStep, showStaffStep);
    const currentIndex = steps.findIndex((s) => s.id === this.state.currentStep);
    if (currentIndex < steps.length - 1) {
      this.setState({ currentStep: steps[currentIndex + 1].id });
    }
  };

  handleBack = () => {
    const showLocationStep = wpbApp?.HideLocations !== 'true' && wpbApp?.locationsCount > 0 && ProLocationStep;
    const showServiceStep = wpbApp?.HideServices !== 'true';
    const showStaffStep = wpbApp?.HideStaffs !== 'true' && ProStaffStep;
    const steps = getSteps(showLocationStep, showServiceStep, showStaffStep);
    const currentIndex = steps.findIndex((s) => s.id === this.state.currentStep);
    if (currentIndex > 0) {
      this.setState({ currentStep: steps[currentIndex - 1].id });
    }
  };

  renderStep = () => {
    const { state, updateInput } = this.props;
    const { currentStep } = this.state;

    switch (currentStep) {
      case 'location':
        return ProLocationStep ? <ProLocationStep state={state} updateInput={updateInput} onNext={this.handleNext} /> : null;
      case 'service':
        return <ServiceStep state={state} updateInput={updateInput} onNext={this.handleNext} onBack={this.handleBack} />;
      case 'staff':
        return ProStaffStep ? <ProStaffStep state={state} updateInput={updateInput} onNext={this.handleNext} onBack={this.handleBack} /> : null;
      case 'date_time':
        return (
          <DateTimeStep
            state={state}
            updateInput={updateInput}
            onNext={this.handleNext}
            onBack={this.handleBack}
          />
        );
      case 'information':
        return (
          <InfoStep
            state={state}
            updateInput={updateInput}
            onNext={this.handleNext}
            onBack={this.handleBack}
          />
        );
      case 'payments':
        return (
          <PaymentStep
            state={state}
            updateInput={updateInput}
            onNext={this.handleNext}
            onBack={this.handleBack}
          />
        );
      case 'confirmation':
        return (
          <ConfirmationStep 
            state={state} 
            data={{
              gcalForCustomer: state.gcalForCustomer,
              ocalForCustomer: state.ocalForCustomer,
              currencySymbol: state.currencySymbol,
              timeFormat: state.timeFormat,
            }}
          />
        );
      default:
        return null;
    }
  };

  render() {
    const { state } = this.props;
    const { currentStep } = this.state;

    const showLocationStep = wpbApp?.HideLocations !== 'true' && wpbApp?.locationsCount > 0 && ProLocationStep;
    const showServiceStep = wpbApp?.HideServices !== 'true';
    const showStaffStep = wpbApp?.HideStaffs !== 'true' && ProStaffStep;
    const steps = getSteps(showLocationStep, showServiceStep, showStaffStep);
    const currentStepIndex = Math.max(0, steps.findIndex((s) => s.id === currentStep));

    return (
      <div className="w-[45rem] bg-white rounded-lg shadow-xl overflow-hidden flex flex-col md:flex-row h-[566px] border border-slate-150">
        <aside className="w-[200px] max-w-[200px] bg-slate-50 border-r border-slate-100 flex flex-col py-[20px] px-[13px] space-y-8">

          <nav className="flex-1 space-y-2">
            {steps.map((step, index) => {
              const Icon = step.icon;
              const isActive = step.id === currentStep;
              const isPast = steps.findIndex((s) => s.id === currentStep) > index;

              return (
                <div
                  key={step.id}
                  className={`flex items-center rounded-xl p-1 transition-all duration-400 ${isActive ? 'bg-white text-blue shadow-lg shadow-white-100 scale-[1]' : 'text-slate-500 hover:bg-slate-100'}`}
                >
                  <div className={`flex items-center space-x-1`}>
                    <div
                      className={`p-2 rounded-lg ${isPast && !isActive ? 'text-blue-600' : ''}`}
                    >
                      <Icon size={18} />
                    </div>
                    <span className="font-medium text-sm">{step.label}</span>
                  </div>
                  {isPast && !isActive && (
                    <div className="ml-auto">
                      <CircleCheckBig size={12} color="#2563eb" />
                    </div>
                  )}
                </div>
              );
            })}
          </nav>
          {state.showFormSupportLink && (
            <a href={state.supportLinkUrl || "#"} target="_blank"
              className="flex items-center justify-center space-x-2 text-slate-400 hover:text-blue-600 focus:outline-none transition-colors px-3 py-2 text-sm font-medium no-underline"
            >
              <HelpCircle size={18} />
              <span>{state.supportLinkText || __('Need Help?', 'bookify')}</span>
            </a>
          )}
        </aside>

        <main className="flex-1 flex flex-col bg-white w-40">
          <header className="px-[20px] py-[21px] border-b border-slate-150 flex justify-between items-center">
            <h2 className="text-2xl md:text-2xl font-semibold text-slate-700">
              {steps[currentStepIndex].id === 'confirmation'
                ? __('Booking Successful', 'bookify')
                : steps[currentStepIndex].title}
            </h2>
            {currentStep !== 'confirmation' && (
              <div className="text-xs font-semibold text-slate-400">
                {sprintf(__('Step %1$s of %2$s', 'bookify'), currentStepIndex + 1, Math.max(steps.length - 1, 1))}
              </div>
            )}
          </header>

          <section className="bookify-light-panel-body flex-1 overflow-y-auto flex flex-col">
            <div className="flex-1 flex flex-col">{this.renderStep()}</div>
          </section>
        </main>
      </div>
    );
  }
}

const LightFrontendApp = () => {
  const state = useBookingStore((s) => s);
  return <LightFrontendAppClass state={state} updateInput={updateInput} />;
};

export default LightFrontendApp;
