/**
 * Business Hours Settings
 *
 * Configure weekly operating hours that automatically block customer bookings
 * outside those times while allowing staff manual override.
 */

import React, { useState, useEffect } from 'react';
import { useTimeBlocks, useCreateTimeBlock, useUpdateTimeBlock, useDeleteTimeBlock } from '../../hooks/useTimeBlocks';
import { Button, FormInput, Alert, LoadingSpinner, Card } from '../../components/ui';
import { BlockPurpose, TimeBlock } from '../../types';

interface DayHours {
  enabled: boolean;
  open: string;  // "09:00"
  close: string; // "17:00"
}

interface BusinessHours {
  monday: DayHours;
  tuesday: DayHours;
  wednesday: DayHours;
  thursday: DayHours;
  friday: DayHours;
  saturday: DayHours;
  sunday: DayHours;
}

const DAYS = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'] as const;
const DAY_LABELS: Record<typeof DAYS[number], string> = {
  monday: 'Monday',
  tuesday: 'Tuesday',
  wednesday: 'Wednesday',
  thursday: 'Thursday',
  friday: 'Friday',
  saturday: 'Saturday',
  sunday: 'Sunday',
};

const DAY_INDICES: Record<typeof DAYS[number], number> = {
  monday: 0,
  tuesday: 1,
  wednesday: 2,
  thursday: 3,
  friday: 4,
  saturday: 5,
  sunday: 6,
};

const DEFAULT_HOURS: BusinessHours = {
  monday: { enabled: true, open: '09:00', close: '17:00' },
  tuesday: { enabled: true, open: '09:00', close: '17:00' },
  wednesday: { enabled: true, open: '09:00', close: '17:00' },
  thursday: { enabled: true, open: '09:00', close: '17:00' },
  friday: { enabled: true, open: '09:00', close: '17:00' },
  saturday: { enabled: false, open: '09:00', close: '17:00' },
  sunday: { enabled: false, open: '09:00', close: '17:00' },
};

const BusinessHoursSettings: React.FC = () => {
  const [hours, setHours] = useState<BusinessHours>(DEFAULT_HOURS);
  const [error, setError] = useState<string>('');
  const [success, setSuccess] = useState<string>('');
  const [isSaving, setIsSaving] = useState(false);

  // Fetch existing business hours time blocks
  const { data: timeBlocks, isLoading } = useTimeBlocks({
    purpose: 'BUSINESS_HOURS' as BlockPurpose,
    is_active: true,
  });

  const createTimeBlock = useCreateTimeBlock();
  const updateTimeBlock = useUpdateTimeBlock();
  const deleteTimeBlock = useDeleteTimeBlock();

  // Parse existing time blocks into UI state
  useEffect(() => {
    if (!timeBlocks || timeBlocks.length === 0) return;

    const parsed: BusinessHours = { ...DEFAULT_HOURS };

    // Group blocks by day
    timeBlocks.forEach((block) => {
      if (block.recurrence_type === 'WEEKLY' && block.recurrence_pattern?.days_of_week) {
        const daysOfWeek = block.recurrence_pattern.days_of_week;

        daysOfWeek.forEach((dayIndex) => {
          const dayName = Object.keys(DAY_INDICES).find(
            (key) => DAY_INDICES[key as typeof DAYS[number]] === dayIndex
          ) as typeof DAYS[number] | undefined;

          if (dayName) {
            // Check if this is a "before hours" or "after hours" block
            if (block.start_time === '00:00:00') {
              // Before hours block: 00:00 to open time
              parsed[dayName].enabled = true;
              parsed[dayName].open = block.end_time?.substring(0, 5) || '09:00';
            } else if (block.end_time === '23:59:59' || block.end_time === '00:00:00') {
              // After hours block: close time to 24:00
              parsed[dayName].enabled = true;
              parsed[dayName].close = block.start_time?.substring(0, 5) || '17:00';
            }
          }
        });
      }
    });

    setHours(parsed);
  }, [timeBlocks]);

  const handleDayToggle = (day: typeof DAYS[number]) => {
    setHours({
      ...hours,
      [day]: {
        ...hours[day],
        enabled: !hours[day].enabled,
      },
    });
  };

  const handleTimeChange = (day: typeof DAYS[number], field: 'open' | 'close', value: string) => {
    setHours({
      ...hours,
      [day]: {
        ...hours[day],
        [field]: value,
      },
    });
  };

  const validateHours = (): boolean => {
    setError('');

    // Check that enabled days have valid times
    for (const day of DAYS) {
      if (hours[day].enabled) {
        const open = hours[day].open;
        const close = hours[day].close;

        if (!open || !close) {
          setError(`Please set both open and close times for ${DAY_LABELS[day]}`);
          return false;
        }

        if (open >= close) {
          setError(`${DAY_LABELS[day]}: Close time must be after open time`);
          return false;
        }
      }
    }

    return true;
  };

  const handleSave = async () => {
    if (!validateHours()) return;

    setIsSaving(true);
    setError('');
    setSuccess('');

    try {
      console.log('Starting save, existing blocks:', timeBlocks);

      // Delete all existing business hours blocks
      if (timeBlocks && timeBlocks.length > 0) {
        console.log('Deleting', timeBlocks.length, 'existing blocks');
        for (const block of timeBlocks) {
          try {
            await deleteTimeBlock.mutateAsync(block.id);
            console.log('Deleted block:', block.id);
          } catch (delErr: any) {
            console.error('Error deleting block:', block.id, delErr);
            throw new Error(`Failed to delete existing block: ${delErr.response?.data?.message || delErr.message}`);
          }
        }
      }

      // Group days by hours for efficient block creation
      const hourGroups: Map<string, number[]> = new Map();

      DAYS.forEach((day) => {
        if (hours[day].enabled) {
          const key = `${hours[day].open}-${hours[day].close}`;
          const dayIndex = DAY_INDICES[day];

          if (!hourGroups.has(key)) {
            hourGroups.set(key, []);
          }
          hourGroups.get(key)!.push(dayIndex);
        }
      });

      console.log('Hour groups:', Array.from(hourGroups.entries()));

      // Create new time blocks for each group
      for (const [hoursKey, daysOfWeek] of hourGroups.entries()) {
        const [open, close] = hoursKey.split('-');

        // Before hours block: 00:00 to open time
        try {
          const beforeBlock = await createTimeBlock.mutateAsync({
            title: 'Before Business Hours',
            purpose: 'BUSINESS_HOURS' as BlockPurpose,
            block_type: 'SOFT',
            resource: null,
            recurrence_type: 'WEEKLY',
            recurrence_pattern: { days_of_week: daysOfWeek },
            all_day: false,
            start_time: '00:00:00',
            end_time: `${open}:00`,
            is_active: true,
          });
          console.log('Created before-hours block:', beforeBlock);
        } catch (createErr: any) {
          console.error('Error creating before-hours block:', createErr);
          throw new Error(`Failed to create before-hours block: ${createErr.response?.data?.message || createErr.message}`);
        }

        // After hours block: close time to 23:59:59
        try {
          const afterBlock = await createTimeBlock.mutateAsync({
            title: 'After Business Hours',
            purpose: 'BUSINESS_HOURS' as BlockPurpose,
            block_type: 'SOFT',
            resource: null,
            recurrence_type: 'WEEKLY',
            recurrence_pattern: { days_of_week: daysOfWeek },
            all_day: false,
            start_time: `${close}:00`,
            end_time: '23:59:59',
            is_active: true,
          });
          console.log('Created after-hours block:', afterBlock);
        } catch (createErr: any) {
          console.error('Error creating after-hours block:', createErr);
          throw new Error(`Failed to create after-hours block: ${createErr.response?.data?.message || createErr.message}`);
        }
      }

      console.log('Save completed successfully');
      setSuccess('Business hours saved successfully! Customer bookings will be blocked outside these hours.');
    } catch (err: any) {
      console.error('Save error:', err);
      setError(err.message || err.response?.data?.message || 'Failed to save business hours. Please try again.');
    } finally {
      setIsSaving(false);
    }
  };

  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-64">
        <LoadingSpinner size="lg" />
      </div>
    );
  }

  return (
    <div className="max-w-4xl mx-auto p-6">
      <div className="mb-6">
        <h1 className="text-2xl font-bold text-gray-900 dark:text-white">Business Hours</h1>
        <p className="mt-2 text-sm text-gray-600 dark:text-gray-400">
          Set your regular operating hours. Customer bookings will be blocked outside these times,
          but staff can still manually schedule appointments if needed.
        </p>
      </div>

      {error && (
        <Alert variant="error" className="mb-4">
          {error}
        </Alert>
      )}

      {success && (
        <Alert variant="success" className="mb-4">
          {success}
        </Alert>
      )}

      <Card>
        <div className="space-y-4">
          {DAYS.map((day) => (
            <div
              key={day}
              className="flex items-center gap-4 p-4 bg-gray-50 dark:bg-gray-800 rounded-lg"
            >
              <div className="flex items-center gap-3 w-40">
                <input
                  type="checkbox"
                  id={`${day}-enabled`}
                  checked={hours[day].enabled}
                  onChange={() => handleDayToggle(day)}
                  className="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600"
                />
                <label
                  htmlFor={`${day}-enabled`}
                  className="text-sm font-medium text-gray-900 dark:text-white cursor-pointer"
                >
                  {DAY_LABELS[day]}
                </label>
              </div>

              {hours[day].enabled ? (
                <div className="flex items-center gap-4 flex-1">
                  <div className="flex items-center gap-2">
                    <label className="text-sm text-gray-600 dark:text-gray-400">Open:</label>
                    <input
                      type="time"
                      value={hours[day].open}
                      onChange={(e) => handleTimeChange(day, 'open', e.target.value)}
                      className="px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
                    />
                  </div>
                  <div className="flex items-center gap-2">
                    <label className="text-sm text-gray-600 dark:text-gray-400">Close:</label>
                    <input
                      type="time"
                      value={hours[day].close}
                      onChange={(e) => handleTimeChange(day, 'close', e.target.value)}
                      className="px-3 py-2 text-sm border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:text-white"
                    />
                  </div>
                  <div className="text-sm text-gray-500 dark:text-gray-400">
                    ({calculateHours(hours[day].open, hours[day].close)} hours)
                  </div>
                </div>
              ) : (
                <div className="text-sm text-gray-500 dark:text-gray-400 flex-1">
                  Closed
                </div>
              )}
            </div>
          ))}
        </div>

        <div className="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
          <div className="flex items-center justify-between">
            <div className="text-sm text-gray-600 dark:text-gray-400">
              <strong>Note:</strong> These hours apply to customer bookings only. Staff can override.
            </div>
            <Button
              onClick={handleSave}
              disabled={isSaving}
              variant="primary"
            >
              {isSaving ? 'Saving...' : 'Save Business Hours'}
            </Button>
          </div>
        </div>
      </Card>

      {/* Preview */}
      <Card className="mt-6">
        <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
          Preview
        </h3>
        <div className="space-y-2">
          {DAYS.map((day) => (
            <div key={day} className="flex items-center justify-between text-sm">
              <span className="font-medium text-gray-900 dark:text-white">
                {DAY_LABELS[day]}:
              </span>
              <span className="text-gray-600 dark:text-gray-400">
                {hours[day].enabled
                  ? `${formatTime(hours[day].open)} - ${formatTime(hours[day].close)}`
                  : 'Closed'}
              </span>
            </div>
          ))}
        </div>
      </Card>
    </div>
  );
};

// Helper functions
const calculateHours = (open: string, close: string): string => {
  try {
    if (!open || !close || !open.includes(':') || !close.includes(':')) {
      return '0';
    }

    const [openHour, openMin] = open.split(':').map(Number);
    const [closeHour, closeMin] = close.split(':').map(Number);

    if (isNaN(openHour) || isNaN(openMin) || isNaN(closeHour) || isNaN(closeMin)) {
      return '0';
    }

    const totalMinutes = (closeHour * 60 + closeMin) - (openHour * 60 + openMin);
    const hours = Math.floor(totalMinutes / 60);
    const minutes = totalMinutes % 60;

    if (minutes === 0) return `${hours}`;
    return `${hours}.${minutes < 10 ? '0' : ''}${minutes}`;
  } catch (e) {
    return '0';
  }
};

const formatTime = (time: string): string => {
  try {
    if (!time || !time.includes(':')) {
      return time;
    }

    const [hour, min] = time.split(':').map(Number);

    if (isNaN(hour) || isNaN(min)) {
      return time;
    }

    const period = hour >= 12 ? 'PM' : 'AM';
    const displayHour = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
    return `${displayHour}:${min.toString().padStart(2, '0')} ${period}`;
  } catch (e) {
    return time;
  }
};

export default BusinessHoursSettings;
