import { useState, useCallback, useMemo, useEffect, useRef } from 'react';
import type {
  QuoteData,
  QuoteResult,
  QuoteBreakdown,
  CompanyInfo,
  GPSSelection,
  SupportSelection,
  VoIPSelection,
  WebHostingSelection,
  EmailSelection,
  ContactInfo,
  GPSTierId,
  SupportPlanId,
  BlockTimeId,
  VoIPTierId,
  WebHostingTierId,
  EmailTierId,
  EmailProvider,
  Industry,
  ContactPreference,
  ClientType,
  ServiceInterests,
} from '@/types/quote';
import {
  gpsTiers,
  equipmentMonitoring,
  supportPlans,
  blockTimeOptions,
  voipTiers,
  voipHardware,
  webHostingTiers,
  emailTiers,
} from '@/lib/pricing-data';

const DRAFT_STORAGE_KEY = 'quote-wizard-draft';

/**
 * Load saved draft from localStorage if available.
 * Returns partial state keyed by section, or null if nothing saved.
 */
function loadDraft(): {
  clientType?: ClientType;
  serviceInterests?: ServiceInterests;
  company?: CompanyInfo;
  gps?: GPSSelection;
  support?: SupportSelection;
  voip?: VoIPSelection;
  webHosting?: WebHostingSelection;
  email?: EmailSelection;
  contact?: ContactInfo;
  accessToken?: string;
} | null {
  try {
    const raw = localStorage.getItem(DRAFT_STORAGE_KEY);
    if (!raw) return null;
    return JSON.parse(raw);
  } catch {
    return null;
  }
}

/**
 * Initial state values
 */
const initialClientType: ClientType = 'company';

const initialServiceInterests: ServiceInterests = {
  gps: true,
  support: true,
  voip: false,
  webHosting: false,
  email: false,
};

const initialCompanyInfo: CompanyInfo = {
  name: '',
  endpointCount: 10,
  industry: '',
  notes: '',
};

const initialGPSSelection: GPSSelection = {
  tierId: 'pro',
  endpointCount: 10,
  includeEquipment: false,
  equipmentDeviceCount: 0,
};

const initialSupportSelection: SupportSelection = {
  planId: 'standard',
  useBlockTime: false,
  blockTimeId: null,
};

const initialVoIPSelection: VoIPSelection = {
  enabled: false,
  tierId: 'voip-standard',
  userCount: 0,
  hardware: [],
};

const initialWebHostingSelection: WebHostingSelection = {
  enabled: false,
  tierId: 'hosting-business',
};

const initialEmailSelection: EmailSelection = {
  enabled: false,
  provider: 'm365',
  tierId: 'm365-standard',
  mailboxCount: 0,
};

const initialContactInfo: ContactInfo = {
  name: '',
  email: '',
  phone: '',
  companyName: '',
  currentITSituation: '',
  contactPreference: 'email',
  agreedToTerms: false,
};

/**
 * Hook return type
 */
export interface UseQuoteReturn {
  quoteData: QuoteData;
  quoteResult: QuoteResult | null;

  // Client type & service interests
  setClientType: (type: ClientType) => void;
  setServiceInterest: (service: keyof ServiceInterests, enabled: boolean) => void;

  // Company updates
  updateCompany: (data: Partial<CompanyInfo>) => void;
  setEndpointCount: (count: number) => void;
  setIndustry: (industry: Industry | '') => void;

  // GPS updates
  updateGPS: (data: Partial<GPSSelection>) => void;
  setGPSTier: (tierId: GPSTierId) => void;
  setEquipmentEnabled: (enabled: boolean) => void;
  setEquipmentCount: (count: number) => void;

  // Support updates
  updateSupport: (data: Partial<SupportSelection>) => void;
  setSupportPlan: (planId: SupportPlanId) => void;
  setBlockTimeEnabled: (enabled: boolean) => void;
  setBlockTime: (blockTimeId: BlockTimeId) => void;

  // VoIP updates
  updateVoIP: (data: Partial<VoIPSelection>) => void;
  setVoIPEnabled: (enabled: boolean) => void;
  setVoIPTier: (tierId: VoIPTierId) => void;
  setVoIPUserCount: (count: number) => void;
  addHardware: (hardwareId: string, quantity: number, isRental: boolean) => void;
  removeHardware: (hardwareId: string) => void;
  updateHardwareQuantity: (hardwareId: string, quantity: number) => void;

  // Web Hosting updates
  updateWebHosting: (data: Partial<WebHostingSelection>) => void;
  setWebHostingEnabled: (enabled: boolean) => void;
  setWebHostingTier: (tierId: WebHostingTierId) => void;

  // Email updates
  updateEmail: (data: Partial<EmailSelection>) => void;
  setEmailEnabled: (enabled: boolean) => void;
  setEmailProvider: (provider: EmailProvider) => void;
  setEmailTier: (tierId: EmailTierId) => void;
  setMailboxCount: (count: number) => void;

  // Contact updates
  updateContact: (data: Partial<ContactInfo>) => void;
  setContactPreference: (preference: ContactPreference) => void;
  setAgreedToTerms: (agreed: boolean) => void;

  // Calculations
  calculateQuote: () => QuoteResult;
  getGPSMonthly: () => number;
  getSupportMonthly: () => number;
  getVoIPMonthly: () => number;
  getWebHostingMonthly: () => number;
  getEmailMonthly: () => number;
  getSupportBlockTimeOneTime: () => number;
  getVoIPOneTime: () => number;

  // Reset
  resetQuote: () => void;
}

/**
 * Quote calculation and state management hook
 */
export function useQuote(): UseQuoteReturn {
  const draft = useRef(loadDraft());

  const [clientType, setClientType] = useState<ClientType>(draft.current?.clientType ?? initialClientType);
  const [serviceInterests, setServiceInterests] = useState<ServiceInterests>(draft.current?.serviceInterests ?? initialServiceInterests);
  const [company, setCompany] = useState<CompanyInfo>(draft.current?.company ?? initialCompanyInfo);
  const [gps, setGPS] = useState<GPSSelection>(draft.current?.gps ?? initialGPSSelection);
  const [support, setSupport] = useState<SupportSelection>(draft.current?.support ?? initialSupportSelection);
  const [voip, setVoIP] = useState<VoIPSelection>(draft.current?.voip ?? initialVoIPSelection);
  const [webHosting, setWebHosting] = useState<WebHostingSelection>(draft.current?.webHosting ?? initialWebHostingSelection);
  const [email, setEmail] = useState<EmailSelection>(draft.current?.email ?? initialEmailSelection);
  const [contact, setContact] = useState<ContactInfo>(draft.current?.contact ?? initialContactInfo);
  const [quoteResult, setQuoteResult] = useState<QuoteResult | null>(null);

  // Persist draft to localStorage when any section changes (debounced)
  const saveTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  useEffect(() => {
    if (saveTimerRef.current) {
      clearTimeout(saveTimerRef.current);
    }
    saveTimerRef.current = setTimeout(() => {
      try {
        // Preserve the accessToken that WizardContainer may have written
        const existing = localStorage.getItem(DRAFT_STORAGE_KEY);
        let accessToken: string | undefined;
        if (existing) {
          try {
            accessToken = JSON.parse(existing).accessToken;
          } catch {
            // ignore
          }
        }
        const payload = {
          clientType,
          serviceInterests,
          company,
          gps,
          support,
          voip,
          webHosting,
          email,
          contact,
          ...(accessToken ? { accessToken } : {}),
        };
        localStorage.setItem(DRAFT_STORAGE_KEY, JSON.stringify(payload));
      } catch {
        // localStorage write failures are non-critical
      }
    }, 500);

    return () => {
      if (saveTimerRef.current) {
        clearTimeout(saveTimerRef.current);
      }
    };
  }, [clientType, serviceInterests, company, gps, support, voip, webHosting, email, contact]);

  // Combined quote data
  const quoteData: QuoteData = useMemo(
    () => ({
      clientType,
      serviceInterests,
      company,
      gps,
      support,
      voip,
      webHosting,
      email,
      contact,
    }),
    [clientType, serviceInterests, company, gps, support, voip, webHosting, email, contact]
  );

  // ============================================================================
  // Client Type & Service Interests
  // ============================================================================

  const setClientTypeValue = useCallback((type: ClientType) => {
    setClientType(type);
  }, []);

  const setServiceInterest = useCallback((service: keyof ServiceInterests, enabled: boolean) => {
    setServiceInterests((prev) => ({ ...prev, [service]: enabled }));
    // Sync the enabled flags on the corresponding selections
    if (service === 'voip') {
      setVoIP((prev) => ({ ...prev, enabled, userCount: enabled ? Math.max(prev.userCount, 1) : 0 }));
    }
    if (service === 'webHosting') {
      setWebHosting((prev) => ({ ...prev, enabled }));
    }
    if (service === 'email') {
      setEmail((prev) => ({ ...prev, enabled, mailboxCount: enabled ? Math.max(prev.mailboxCount, 1) : 0 }));
    }
  }, []);

  // ============================================================================
  // Company Updates
  // ============================================================================

  const updateCompany = useCallback((data: Partial<CompanyInfo>) => {
    setCompany((prev) => {
      const updated = { ...prev, ...data };
      // Sync endpoint count with GPS selection
      if (data.endpointCount !== undefined) {
        setGPS((gpsState) => ({ ...gpsState, endpointCount: data.endpointCount as number }));
      }
      return updated;
    });
  }, []);

  const setEndpointCount = useCallback((count: number) => {
    const validCount = Math.max(1, count);
    setCompany((prev) => ({ ...prev, endpointCount: validCount }));
    setGPS((prev) => ({ ...prev, endpointCount: validCount }));
  }, []);

  const setIndustry = useCallback((industry: Industry | '') => {
    setCompany((prev) => ({ ...prev, industry }));
  }, []);

  // ============================================================================
  // GPS Updates
  // ============================================================================

  const updateGPS = useCallback((data: Partial<GPSSelection>) => {
    setGPS((prev) => ({ ...prev, ...data }));
  }, []);

  const setGPSTier = useCallback((tierId: GPSTierId) => {
    setGPS((prev) => ({ ...prev, tierId }));
  }, []);

  const setEquipmentEnabled = useCallback((enabled: boolean) => {
    setGPS((prev) => ({
      ...prev,
      includeEquipment: enabled,
      equipmentDeviceCount: enabled ? Math.max(prev.equipmentDeviceCount, 1) : 0,
    }));
  }, []);

  const setEquipmentCount = useCallback((count: number) => {
    setGPS((prev) => ({ ...prev, equipmentDeviceCount: Math.max(0, count) }));
  }, []);

  // ============================================================================
  // Support Updates
  // ============================================================================

  const updateSupport = useCallback((data: Partial<SupportSelection>) => {
    setSupport((prev) => ({ ...prev, ...data }));
  }, []);

  const setSupportPlan = useCallback((planId: SupportPlanId) => {
    setSupport((prev) => ({ ...prev, planId }));
  }, []);

  const setBlockTimeEnabled = useCallback((enabled: boolean) => {
    setSupport((prev) => ({
      ...prev,
      useBlockTime: enabled,
      blockTimeId: enabled ? (prev.blockTimeId || 'block-10') : null,
    }));
  }, []);

  const setBlockTime = useCallback((blockTimeId: BlockTimeId) => {
    setSupport((prev) => ({ ...prev, blockTimeId, useBlockTime: true }));
  }, []);

  // ============================================================================
  // VoIP Updates
  // ============================================================================

  const updateVoIP = useCallback((data: Partial<VoIPSelection>) => {
    setVoIP((prev) => ({ ...prev, ...data }));
  }, []);

  const setVoIPEnabled = useCallback((enabled: boolean) => {
    setVoIP((prev) => ({
      ...prev,
      enabled,
      userCount: enabled ? Math.max(prev.userCount, 1) : 0,
    }));
  }, []);

  const setVoIPTier = useCallback((tierId: VoIPTierId) => {
    setVoIP((prev) => ({ ...prev, tierId }));
  }, []);

  const setVoIPUserCount = useCallback((count: number) => {
    setVoIP((prev) => ({ ...prev, userCount: Math.max(0, count) }));
  }, []);

  const addHardware = useCallback((hardwareId: string, quantity: number, isRental: boolean) => {
    setVoIP((prev) => {
      const existing = prev.hardware.find((h) => h.hardwareId === hardwareId);
      if (existing) {
        return {
          ...prev,
          hardware: prev.hardware.map((h) =>
            h.hardwareId === hardwareId ? { ...h, quantity, isRental } : h
          ),
        };
      }
      return {
        ...prev,
        hardware: [...prev.hardware, { hardwareId, quantity, isRental }],
      };
    });
  }, []);

  const removeHardware = useCallback((hardwareId: string) => {
    setVoIP((prev) => ({
      ...prev,
      hardware: prev.hardware.filter((h) => h.hardwareId !== hardwareId),
    }));
  }, []);

  const updateHardwareQuantity = useCallback((hardwareId: string, quantity: number) => {
    setVoIP((prev) => ({
      ...prev,
      hardware: prev.hardware.map((h) =>
        h.hardwareId === hardwareId ? { ...h, quantity: Math.max(0, quantity) } : h
      ),
    }));
  }, []);

  // ============================================================================
  // Web Hosting Updates
  // ============================================================================

  const updateWebHosting = useCallback((data: Partial<WebHostingSelection>) => {
    setWebHosting((prev) => ({ ...prev, ...data }));
  }, []);

  const setWebHostingEnabled = useCallback((enabled: boolean) => {
    setWebHosting((prev) => ({ ...prev, enabled }));
  }, []);

  const setWebHostingTier = useCallback((tierId: WebHostingTierId) => {
    setWebHosting((prev) => ({ ...prev, tierId }));
  }, []);

  // ============================================================================
  // Email Updates
  // ============================================================================

  const updateEmail = useCallback((data: Partial<EmailSelection>) => {
    setEmail((prev) => ({ ...prev, ...data }));
  }, []);

  const setEmailEnabled = useCallback((enabled: boolean) => {
    setEmail((prev) => ({
      ...prev,
      enabled,
      mailboxCount: enabled ? Math.max(prev.mailboxCount, 1) : 0,
    }));
  }, []);

  const setEmailProvider = useCallback((provider: EmailProvider) => {
    setEmail((prev) => {
      // Set default tier for provider
      const defaultTier = provider === 'm365' ? 'm365-standard' : 'whm-standard';
      return { ...prev, provider, tierId: defaultTier as EmailTierId };
    });
  }, []);

  const setEmailTier = useCallback((tierId: EmailTierId) => {
    setEmail((prev) => ({ ...prev, tierId }));
  }, []);

  const setMailboxCount = useCallback((count: number) => {
    setEmail((prev) => ({ ...prev, mailboxCount: Math.max(0, count) }));
  }, []);

  // ============================================================================
  // Contact Updates
  // ============================================================================

  const updateContact = useCallback((data: Partial<ContactInfo>) => {
    setContact((prev) => ({ ...prev, ...data }));
  }, []);

  const setContactPreference = useCallback((preference: ContactPreference) => {
    setContact((prev) => ({ ...prev, contactPreference: preference }));
  }, []);

  const setAgreedToTerms = useCallback((agreed: boolean) => {
    setContact((prev) => ({ ...prev, agreedToTerms: agreed }));
  }, []);

  // ============================================================================
  // Calculation Functions
  // ============================================================================

  const getGPSMonthly = useCallback((): number => {
    const tier = gpsTiers.find((t) => t.id === gps.tierId);
    if (!tier) return 0;

    let total = tier.pricePerEndpoint * gps.endpointCount;

    if (gps.includeEquipment && gps.equipmentDeviceCount > 0) {
      const additionalDevices = Math.max(0, gps.equipmentDeviceCount - equipmentMonitoring.baseDevices);
      total += equipmentMonitoring.basePrice + (additionalDevices * equipmentMonitoring.additionalDevicePrice);
    }

    return total;
  }, [gps]);

  const getSupportMonthly = useCallback((): number => {
    if (support.planId === 'none') return 0;

    const plan = supportPlans.find((p) => p.id === support.planId);
    return plan ? plan.monthlyPrice : 0;
  }, [support]);

  const getSupportBlockTimeOneTime = useCallback((): number => {
    if (!support.useBlockTime || !support.blockTimeId) return 0;
    const blockTime = blockTimeOptions.find((b) => b.id === support.blockTimeId);
    return blockTime ? blockTime.price : 0;
  }, [support]);

  const getVoIPMonthly = useCallback((): number => {
    if (!voip.enabled) return 0;

    const tier = voipTiers.find((t) => t.id === voip.tierId);
    if (!tier) return 0;

    let total = tier.pricePerUser * voip.userCount;

    // Add rental hardware costs
    voip.hardware.forEach((hw) => {
      if (hw.isRental) {
        const hardware = voipHardware.find((h) => h.id === hw.hardwareId);
        if (hardware) {
          total += hardware.monthlyRental * hw.quantity;
        }
      }
    });

    return total;
  }, [voip]);

  const getVoIPOneTime = useCallback((): number => {
    if (!voip.enabled) return 0;

    let total = 0;

    // Add purchased hardware costs
    voip.hardware.forEach((hw) => {
      if (!hw.isRental) {
        const hardware = voipHardware.find((h) => h.id === hw.hardwareId);
        if (hardware) {
          total += hardware.oneTimePrice * hw.quantity;
        }
      }
    });

    return total;
  }, [voip]);

  const getWebHostingMonthly = useCallback((): number => {
    if (!webHosting.enabled) return 0;

    const tier = webHostingTiers.find((t) => t.id === webHosting.tierId);
    return tier ? tier.monthlyPrice : 0;
  }, [webHosting]);

  const getEmailMonthly = useCallback((): number => {
    if (!email.enabled) return 0;

    const tier = emailTiers.find((t) => t.id === email.tierId);
    return tier ? tier.pricePerMailbox * email.mailboxCount : 0;
  }, [email]);

  const calculateQuote = useCallback((): QuoteResult => {
    // Only include services that are enabled in serviceInterests
    const gpsMonthly = serviceInterests.gps ? getGPSMonthly() : 0;
    const supportMonthly = serviceInterests.support ? getSupportMonthly() : 0;
    const supportBlockTimeOneTime = serviceInterests.support ? getSupportBlockTimeOneTime() : 0;
    const voipMonthly = serviceInterests.voip ? getVoIPMonthly() : 0;
    const voipOneTime = serviceInterests.voip ? getVoIPOneTime() : 0;
    const webHostingMonthly = serviceInterests.webHosting ? getWebHostingMonthly() : 0;
    const emailMonthly = serviceInterests.email ? getEmailMonthly() : 0;

    // Calculate GPS breakdown (only if enabled)
    let gpsMonitoring = 0;
    let gpsEquipment = 0;
    if (serviceInterests.gps) {
      const gpsTier = gpsTiers.find((t) => t.id === gps.tierId);
      gpsMonitoring = gpsTier ? gpsTier.pricePerEndpoint * gps.endpointCount : 0;
      if (gps.includeEquipment && gps.equipmentDeviceCount > 0) {
        const additionalDevices = Math.max(0, gps.equipmentDeviceCount - equipmentMonitoring.baseDevices);
        gpsEquipment = equipmentMonitoring.basePrice + (additionalDevices * equipmentMonitoring.additionalDevicePrice);
      }
    }

    // Calculate support breakdown (only if enabled)
    let supportPlanCost = 0;
    if (serviceInterests.support && support.planId !== 'none') {
      const supportPlan = supportPlans.find((p) => p.id === support.planId);
      supportPlanCost = supportPlan ? supportPlan.monthlyPrice : 0;
    }

    // Calculate VoIP breakdown (only if enabled)
    let voipService = 0;
    let voipHardwareMonthly = 0;
    if (serviceInterests.voip && voip.enabled) {
      const voipTier = voipTiers.find((t) => t.id === voip.tierId);
      voipService = voipTier ? voipTier.pricePerUser * voip.userCount : 0;
      voip.hardware.forEach((hw) => {
        if (hw.isRental) {
          const hardware = voipHardware.find((h) => h.id === hw.hardwareId);
          if (hardware) {
            voipHardwareMonthly += hardware.monthlyRental * hw.quantity;
          }
        }
      });
    }

    const breakdown: QuoteBreakdown = {
      gps: {
        monitoring: gpsMonitoring,
        equipment: gpsEquipment,
        total: gpsMonthly,
      },
      support: {
        plan: supportPlanCost,
        blockTime: supportBlockTimeOneTime,
        total: supportMonthly,
      },
      voip: {
        service: voipService,
        hardware: voipHardwareMonthly,
        total: voipMonthly,
      },
      webHosting: webHostingMonthly,
      email: emailMonthly,
    };

    const monthlyTotal = gpsMonthly + supportMonthly + voipMonthly + webHostingMonthly + emailMonthly;

    const result: QuoteResult = {
      monthlyTotal,
      oneTimeTotal: voipOneTime + supportBlockTimeOneTime,
      breakdown,
      gpsMonthly,
      supportMonthly,
      voipMonthly,
      webHostingMonthly,
      emailMonthly,
    };

    setQuoteResult(result);
    return result;
  }, [serviceInterests, gps, support, voip, webHosting, email, getGPSMonthly, getSupportMonthly, getSupportBlockTimeOneTime, getVoIPMonthly, getVoIPOneTime, getWebHostingMonthly, getEmailMonthly]);

  // ============================================================================
  // Reset
  // ============================================================================

  const resetQuote = useCallback(() => {
    setClientType(initialClientType);
    setServiceInterests(initialServiceInterests);
    setCompany(initialCompanyInfo);
    setGPS(initialGPSSelection);
    setSupport(initialSupportSelection);
    setVoIP(initialVoIPSelection);
    setWebHosting(initialWebHostingSelection);
    setEmail(initialEmailSelection);
    setContact(initialContactInfo);
    setQuoteResult(null);
    localStorage.removeItem(DRAFT_STORAGE_KEY);
  }, []);

  return {
    quoteData,
    quoteResult,

    // Client type & service interests
    setClientType: setClientTypeValue,
    setServiceInterest,

    // Company updates
    updateCompany,
    setEndpointCount,
    setIndustry,

    // GPS updates
    updateGPS,
    setGPSTier,
    setEquipmentEnabled,
    setEquipmentCount,

    // Support updates
    updateSupport,
    setSupportPlan,
    setBlockTimeEnabled,
    setBlockTime,

    // VoIP updates
    updateVoIP,
    setVoIPEnabled,
    setVoIPTier,
    setVoIPUserCount,
    addHardware,
    removeHardware,
    updateHardwareQuantity,

    // Web Hosting updates
    updateWebHosting,
    setWebHostingEnabled,
    setWebHostingTier,

    // Email updates
    updateEmail,
    setEmailEnabled,
    setEmailProvider,
    setEmailTier,
    setMailboxCount,

    // Contact updates
    updateContact,
    setContactPreference,
    setAgreedToTerms,

    // Calculations
    calculateQuote,
    getGPSMonthly,
    getSupportMonthly,
    getVoIPMonthly,
    getWebHostingMonthly,
    getEmailMonthly,
    getSupportBlockTimeOneTime,
    getVoIPOneTime,

    // Reset
    resetQuote,
  };
}
