import React, { useMemo, useState, useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import GridLayout, { Layout } from 'react-grid-layout';
import 'react-grid-layout/css/styles.css';
import 'react-resizable/css/styles.css';
import { Settings, Calendar, Users, Briefcase, ClipboardList, Edit2, Check } from 'lucide-react';
import { useServices } from '../hooks/useServices';
import { useResources } from '../hooks/useResources';
import { useAppointments } from '../hooks/useAppointments';
import { useCustomers } from '../hooks/useCustomers';
import { useTickets } from '../hooks/useTickets';
import { subDays, subMonths, isAfter, startOfWeek, endOfWeek, isWithinInterval } from 'date-fns';
import {
  MetricWidget,
  ChartWidget,
  OpenTicketsWidget,
  RecentActivityWidget,
  CapacityWidget,
  NoShowRateWidget,
  CustomerBreakdownWidget,
  WidgetConfigModal,
  WIDGET_DEFINITIONS,
  DEFAULT_LAYOUT,
  DashboardLayout,
  WidgetType,
} from '../components/dashboard';

const STORAGE_KEY = 'dashboard_layout';

const Dashboard: React.FC = () => {
  const { t } = useTranslation();
  const { data: services, isLoading: servicesLoading } = useServices();
  const { data: resources, isLoading: resourcesLoading } = useResources();
  const { data: appointments, isLoading: appointmentsLoading } = useAppointments();
  const { data: customers, isLoading: customersLoading } = useCustomers();
  const { data: tickets, isLoading: ticketsLoading } = useTickets();

  const [isEditing, setIsEditing] = useState(false);
  const [showConfig, setShowConfig] = useState(false);
  const [dashboardLayout, setDashboardLayout] = useState<DashboardLayout>(() => {
    const saved = localStorage.getItem(STORAGE_KEY);
    if (saved) {
      try {
        return JSON.parse(saved);
      } catch {
        return DEFAULT_LAYOUT;
      }
    }
    return DEFAULT_LAYOUT;
  });

  // Save layout to localStorage when it changes
  useEffect(() => {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(dashboardLayout));
  }, [dashboardLayout]);

  const isLoading = servicesLoading || resourcesLoading || appointmentsLoading || customersLoading || ticketsLoading;

  // Calculate growth percentages
  const calculateGrowth = useCallback((
    items: any[],
    dateField: string,
    filterFn?: (item: any) => boolean
  ) => {
    const now = new Date();
    const oneWeekAgo = subDays(now, 7);
    const twoWeeksAgo = subDays(now, 14);
    const oneMonthAgo = subMonths(now, 1);
    const twoMonthsAgo = subMonths(now, 2);

    const filteredItems = filterFn ? items.filter(filterFn) : items;

    const thisWeek = filteredItems.filter(item => {
      const date = new Date(item[dateField]);
      return isAfter(date, oneWeekAgo);
    }).length;

    const lastWeek = filteredItems.filter(item => {
      const date = new Date(item[dateField]);
      return isAfter(date, twoWeeksAgo) && !isAfter(date, oneWeekAgo);
    }).length;

    const thisMonth = filteredItems.filter(item => {
      const date = new Date(item[dateField]);
      return isAfter(date, oneMonthAgo);
    }).length;

    const lastMonth = filteredItems.filter(item => {
      const date = new Date(item[dateField]);
      return isAfter(date, twoMonthsAgo) && !isAfter(date, oneMonthAgo);
    }).length;

    const weeklyChange = lastWeek !== 0 ? ((thisWeek - lastWeek) / lastWeek) * 100 : (thisWeek > 0 ? 100 : 0);
    const monthlyChange = lastMonth !== 0 ? ((thisMonth - lastMonth) / lastMonth) * 100 : (thisMonth > 0 ? 100 : 0);

    return {
      weekly: { value: thisWeek, change: weeklyChange },
      monthly: { value: thisMonth, change: monthlyChange },
    };
  }, []);

  // Calculate metrics with real growth data
  const metrics = useMemo(() => {
    if (!appointments || !customers || !services || !resources) {
      return {
        appointments: { count: 0, growth: { weekly: { value: 0, change: 0 }, monthly: { value: 0, change: 0 } } },
        customers: { count: 0, growth: { weekly: { value: 0, change: 0 }, monthly: { value: 0, change: 0 } } },
        services: { count: 0 },
        resources: { count: 0 },
      };
    }

    const activeCustomers = customers.filter(c => c.status === 'Active');

    return {
      appointments: {
        count: appointments.length,
        growth: calculateGrowth(appointments, 'startTime'),
      },
      customers: {
        count: activeCustomers.length,
        growth: calculateGrowth(customers, 'lastVisit', c => c.status === 'Active' && c.lastVisit),
      },
      services: { count: services.length },
      resources: { count: resources.length },
    };
  }, [appointments, customers, services, resources, calculateGrowth]);

  // Calculate weekly chart data
  const weeklyData = useMemo(() => {
    if (!appointments) {
      return { revenue: [], appointments: [] };
    }

    const now = new Date();
    const weekStart = startOfWeek(now, { weekStartsOn: 1 });
    const weekEnd = endOfWeek(now, { weekStartsOn: 1 });

    const dayMap: Record<string, { revenue: number; count: number }> = {
      Mon: { revenue: 0, count: 0 },
      Tue: { revenue: 0, count: 0 },
      Wed: { revenue: 0, count: 0 },
      Thu: { revenue: 0, count: 0 },
      Fri: { revenue: 0, count: 0 },
      Sat: { revenue: 0, count: 0 },
      Sun: { revenue: 0, count: 0 },
    };

    appointments
      .filter(appt => isWithinInterval(new Date(appt.startTime), { start: weekStart, end: weekEnd }))
      .forEach(appt => {
        const date = new Date(appt.startTime);
        const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
        const dayName = dayNames[date.getDay()];

        dayMap[dayName].count++;
        dayMap[dayName].revenue += (appt as any).price || 0;
      });

    const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    return {
      revenue: days.map(day => ({ name: day, value: dayMap[day].revenue })),
      appointments: days.map(day => ({ name: day, value: dayMap[day].count })),
    };
  }, [appointments]);

  // Handle layout change
  const onLayoutChange = useCallback((newLayout: Layout[]) => {
    setDashboardLayout(prev => ({
      ...prev,
      layout: newLayout,
    }));
  }, []);

  // Toggle widget visibility
  const toggleWidget = useCallback((widgetId: string) => {
    setDashboardLayout(prev => {
      const isActive = prev.widgets.includes(widgetId);
      if (isActive) {
        return {
          widgets: prev.widgets.filter(id => id !== widgetId),
          layout: prev.layout.filter(l => l.i !== widgetId),
        };
      } else {
        const widgetDef = WIDGET_DEFINITIONS[widgetId as WidgetType];
        const maxY = Math.max(0, ...prev.layout.map(l => l.y + l.h));
        return {
          widgets: [...prev.widgets, widgetId],
          layout: [
            ...prev.layout,
            {
              i: widgetId,
              x: 0,
              y: maxY,
              w: widgetDef.defaultSize.w,
              h: widgetDef.defaultSize.h,
              minW: widgetDef.minSize?.w,
              minH: widgetDef.minSize?.h,
            },
          ],
        };
      }
    });
  }, []);

  // Remove widget
  const removeWidget = useCallback((widgetId: string) => {
    setDashboardLayout(prev => ({
      widgets: prev.widgets.filter(id => id !== widgetId),
      layout: prev.layout.filter(l => l.i !== widgetId),
    }));
  }, []);

  // Reset to default layout
  const resetLayout = useCallback(() => {
    setDashboardLayout(DEFAULT_LAYOUT);
  }, []);

  // Render individual widget
  const renderWidget = useCallback((widgetId: string) => {
    const widgetProps = {
      isEditing,
      onRemove: () => removeWidget(widgetId),
    };

    switch (widgetId) {
      case 'appointments-metric':
        return (
          <MetricWidget
            key={widgetId}
            title={t('dashboard.totalAppointments')}
            value={metrics.appointments.count}
            growth={metrics.appointments.growth}
            icon={<Calendar size={18} />}
            {...widgetProps}
          />
        );
      case 'customers-metric':
        return (
          <MetricWidget
            key={widgetId}
            title={t('customers.title')}
            value={metrics.customers.count}
            growth={metrics.customers.growth}
            icon={<Users size={18} />}
            {...widgetProps}
          />
        );
      case 'services-metric':
        return (
          <MetricWidget
            key={widgetId}
            title={t('services.title')}
            value={metrics.services.count}
            growth={{ weekly: { value: 0, change: 0 }, monthly: { value: 0, change: 0 } }}
            icon={<Briefcase size={18} />}
            {...widgetProps}
          />
        );
      case 'resources-metric':
        return (
          <MetricWidget
            key={widgetId}
            title={t('resources.title')}
            value={metrics.resources.count}
            growth={{ weekly: { value: 0, change: 0 }, monthly: { value: 0, change: 0 } }}
            icon={<ClipboardList size={18} />}
            {...widgetProps}
          />
        );
      case 'revenue-chart':
        return (
          <ChartWidget
            key={widgetId}
            title={t('dashboard.totalRevenue')}
            data={weeklyData.revenue}
            type="bar"
            color="#3b82f6"
            valuePrefix="$"
            {...widgetProps}
          />
        );
      case 'appointments-chart':
        return (
          <ChartWidget
            key={widgetId}
            title={t('dashboard.upcomingAppointments')}
            data={weeklyData.appointments}
            type="line"
            color="#10b981"
            {...widgetProps}
          />
        );
      case 'open-tickets':
        return (
          <OpenTicketsWidget
            key={widgetId}
            tickets={tickets || []}
            {...widgetProps}
          />
        );
      case 'recent-activity':
        return (
          <RecentActivityWidget
            key={widgetId}
            appointments={appointments || []}
            customers={customers || []}
            {...widgetProps}
          />
        );
      case 'capacity-utilization':
        return (
          <CapacityWidget
            key={widgetId}
            appointments={appointments || []}
            resources={resources || []}
            {...widgetProps}
          />
        );
      case 'no-show-rate':
        return (
          <NoShowRateWidget
            key={widgetId}
            appointments={appointments || []}
            {...widgetProps}
          />
        );
      case 'customer-breakdown':
        return (
          <CustomerBreakdownWidget
            key={widgetId}
            customers={customers || []}
            {...widgetProps}
          />
        );
      default:
        return null;
    }
  }, [t, metrics, weeklyData, tickets, appointments, customers, resources, isEditing, removeWidget]);

  if (isLoading) {
    return (
      <div className="p-8 space-y-8">
        <div>
          <h2 className="text-2xl font-bold text-gray-900 dark:text-white">{t('dashboard.title')}</h2>
          <p className="text-gray-500 dark:text-gray-400">{t('common.loading')}</p>
        </div>
        <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
          {[1, 2, 3, 4].map((i) => (
            <div key={i} className="p-6 bg-white dark:bg-gray-800 border border-gray-100 dark:border-gray-700 rounded-xl shadow-sm animate-pulse">
              <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-24 mb-2"></div>
              <div className="h-8 bg-gray-200 dark:bg-gray-700 rounded w-16"></div>
            </div>
          ))}
        </div>
      </div>
    );
  }

  // Get layout with min sizes
  const layoutWithConstraints = dashboardLayout.layout.map(l => {
    const widgetDef = WIDGET_DEFINITIONS[l.i as WidgetType];
    return {
      ...l,
      minW: widgetDef?.minSize?.w || 2,
      minH: widgetDef?.minSize?.h || 2,
    };
  });

  return (
    <div className="p-8 space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-2xl font-bold text-gray-900 dark:text-white">{t('dashboard.title')}</h2>
          <p className="text-gray-500 dark:text-gray-400">{t('dashboard.todayOverview')}</p>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={() => setIsEditing(!isEditing)}
            className={`flex items-center gap-2 px-3 py-2 rounded-lg transition-colors ${
              isEditing
                ? 'bg-brand-600 text-white'
                : 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
            }`}
          >
            {isEditing ? <Check size={16} /> : <Edit2 size={16} />}
            <span className="text-sm">{isEditing ? 'Done' : 'Edit Layout'}</span>
          </button>
          <button
            onClick={() => setShowConfig(true)}
            className="flex items-center gap-2 px-3 py-2 bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
          >
            <Settings size={16} />
            <span className="text-sm">Widgets</span>
          </button>
        </div>
      </div>

      {/* Edit mode hint */}
      {isEditing && (
        <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-3 text-sm text-blue-700 dark:text-blue-300">
          Drag widgets to reposition them. Drag the corner to resize. Hover over a widget and click the X to remove it.
        </div>
      )}

      {/* Grid Layout */}
      <div className="max-w-[1200px] mx-auto">
        <GridLayout
          className="layout"
          layout={layoutWithConstraints}
          cols={12}
          rowHeight={60}
          width={1200}
          isDraggable={isEditing}
          isResizable={isEditing}
          onLayoutChange={onLayoutChange}
          draggableHandle=".drag-handle"
          compactType="vertical"
          preventCollision={false}
        >
          {dashboardLayout.widgets.map(widgetId => (
            <div key={widgetId} className="widget-container">
              {renderWidget(widgetId)}
            </div>
          ))}
        </GridLayout>
      </div>

      {/* Widget Config Modal */}
      <WidgetConfigModal
        isOpen={showConfig}
        onClose={() => setShowConfig(false)}
        activeWidgets={dashboardLayout.widgets}
        onToggleWidget={toggleWidget}
        onResetLayout={resetLayout}
      />
    </div>
  );
};

export default Dashboard;
