'use client';

import { useMemo } from 'react';
import { useTranslations } from 'next-intl';
import { useAuth } from '@/lib/hooks/useAuth';
import {
  canViewAppointmentsTab,
  canViewCases,
  canViewLabCasesOrTasks,
  canViewTasks,
  canViewTreatment,
} from '@/components/shared/permissions';
import { KpiCard } from '@/components/today/KpiCard';
import { ChartCard } from '@/components/today/ChartCard';
import { TodayAreaChart } from '@/components/today/TodayAreaChart';
import { TodayBarChart } from '@/components/today/TodayBarChart';
import {
  formatTodayChartDayLabel,
  mapWeekChartBuckets,
  useTodayDayLabelFormatter,
} from '@/components/today/chart-day-labels';
import { TodayDashboardGrid } from '@/components/today/TodayDashboardGrid';
import { TodayDonutChart } from '@/components/today/TodayDonutChart';
import { TodayHorizontalBarChart } from '@/components/today/TodayHorizontalBarChart';
import { TodayCaseCompletionKpiCard } from '@/components/today/TodayCaseCompletionKpiCard';
import { TodayStackedBarChart } from '@/components/today/TodayStackedBarChart';
import { TodaySubscriptionKpiCard } from '@/components/today/TodaySubscriptionKpiCard';
import { TodayUpcomingAppointments } from '@/components/today/TodayUpcomingAppointments';
import {
  ChartCardSkeleton,
  KpiCardSkeleton,
  ListRowSkeleton,
} from '@/components/today/TodaySkeleton';
import {
  TODAY_DASHBOARD_LAYOUT,
  type TodayDashboardCell,
} from '@/components/today/today-dashboard-layout';
import { getEligibleTodayKpis, getVisibleTodayKpis } from '@/components/today/widget-registry';
import { prosthesisTypeColor, prosthesisTypeSwatchStyle } from '@/components/ui/treatment/prosthesisTypeDisplay';
import { treatmentTypeColor } from '@/components/ui/treatment/treatmentTypeDisplay';
import type {
  TodaySubscriptionSnapshot,
  TodaySummaryActions,
  TodaySummaryCharts,
  TodaySummaryWidgets,
} from '@/types/today';

interface TodayDashboardProps {
  widgets: TodaySummaryWidgets;
  charts: TodaySummaryCharts;
  actions: TodaySummaryActions;
  subscription?: TodaySubscriptionSnapshot;
  loading?: boolean;
  isInitialLoad?: boolean;
  hasError?: boolean;
}

export function TodayDashboard({
  widgets,
  charts,
  actions,
  subscription,
  loading = false,
  isInitialLoad = false,
  hasError = false,
}: TodayDashboardProps) {
  const t = useTranslations('today');
  const dayLabelFormatter = useTodayDayLabelFormatter();
  const { currentOrganization } = useAuth();
  const orgType = currentOrganization?.type;
  const isOwner = Boolean(currentOrganization?.isOwner);

  const showUpcoming =
    orgType === 'CLINIC' && currentOrganization && canViewTreatment(currentOrganization);

  const showCharts = useMemo(() => {
    if (!orgType || !currentOrganization) return false;
    if (orgType === 'CLINIC') {
      return (
        canViewAppointmentsTab(currentOrganization) ||
        canViewTreatment(currentOrganization)
      );
    }
    return (
      canViewCases(currentOrganization) ||
      canViewTasks(currentOrganization) ||
      canViewLabCasesOrTasks(currentOrganization)
    );
  }, [currentOrganization, orgType]);

  const kpiDefinitions = isInitialLoad
    ? getEligibleTodayKpis(currentOrganization)
    : getVisibleTodayKpis(currentOrganization, widgets);

  const showSubscriptionCard = isOwner && (isInitialLoad || Boolean(subscription));

  const showCaseCompletionCard =
    orgType === 'LAB' &&
    Boolean(currentOrganization && canViewCases(currentOrganization)) &&
    (isInitialLoad || charts.caseCompletion !== undefined);

  const cells = useMemo(() => {
    if (isInitialLoad) {
      return buildSkeletonCells({
        kpiDefinitions,
        showSubscriptionCard,
        showCaseCompletionCard,
        showUpcoming: Boolean(showUpcoming),
        showCharts,
        orgType,
        isOwner,
        charts,
      });
    }

    return buildDashboardCells({
      t,
      dayLabelFormatter,
      widgets,
      charts,
      actions,
      subscription,
      kpiDefinitions,
      showSubscriptionCard: showSubscriptionCard && Boolean(subscription),
      showCaseCompletionCard:
        showCaseCompletionCard && charts.caseCompletion !== undefined,
      showUpcoming: Boolean(showUpcoming),
      showCharts,
      orgType,
      isOwner,
      currentOrganization,
    });
  }, [
    isInitialLoad,
    kpiDefinitions,
    showSubscriptionCard,
    showCaseCompletionCard,
    showUpcoming,
    showCharts,
    orgType,
    isOwner,
    charts,
    t,
    dayLabelFormatter,
    widgets,
    actions,
    subscription,
    currentOrganization,
  ]);

  if (hasError && !loading && cells.length === 0) {
    return null;
  }

  if (!loading && !hasError && cells.length === 0) {
    return (
      <div className="rounded-[var(--radius-md)] border border-border/60 bg-background-secondary/30 px-4 py-6 text-center">
        <p className="text-sm text-text-muted">{t('noWidgets')}</p>
      </div>
    );
  }

  return <TodayDashboardGrid cells={cells} loading={loading} />;
}

function buildSkeletonCells(options: {
  kpiDefinitions: ReturnType<typeof getEligibleTodayKpis>;
  showSubscriptionCard: boolean;
  showCaseCompletionCard: boolean;
  showUpcoming: boolean;
  showCharts: boolean;
  orgType?: 'CLINIC' | 'LAB';
  isOwner: boolean;
  charts: TodaySummaryCharts;
}): TodayDashboardCell[] {
  const cells: TodayDashboardCell[] = [];

  if (options.showCharts) {
    const chartCount = countVisibleCharts(options.charts, options.orgType, options.isOwner);
    for (let index = 0; index < Math.min(chartCount, 4); index += 1) {
      cells.push({
        id: `chart-skeleton-${index}`,
        layout: TODAY_DASHBOARD_LAYOUT.chart,
        content: <ChartCardSkeleton />,
      });
    }
  }

  if (options.showUpcoming) {
    cells.push({
      id: 'upcoming-skeleton',
      layout: TODAY_DASHBOARD_LAYOUT.upcoming,
      content: (
        <div className="flex h-full min-h-0 flex-col rounded-[var(--radius-lg)] border border-card-border bg-card p-3">
          <div className="mb-2 space-y-1.5">
            <div className="h-3.5 w-32 animate-pulse rounded bg-background-secondary/60" />
            <div className="h-3 w-44 animate-pulse rounded bg-background-secondary/60" />
          </div>
          <div className="space-y-2">
            {[0, 1].map((key) => (
              <ListRowSkeleton key={key} compact />
            ))}
          </div>
        </div>
      ),
    });
  }

  if (options.showSubscriptionCard) {
    cells.push({
      id: 'subscription-skeleton',
      layout: TODAY_DASHBOARD_LAYOUT.subscription,
      content: <KpiCardSkeleton tall />,
    });
  }

  if (options.showCaseCompletionCard) {
    cells.push({
      id: 'case-completion-skeleton',
      layout: TODAY_DASHBOARD_LAYOUT.subscription,
      content: <KpiCardSkeleton tall />,
    });
  }

  for (const definition of options.kpiDefinitions) {
    cells.push({
      id: `kpi-skeleton-${definition.key}`,
      layout: TODAY_DASHBOARD_LAYOUT.kpi,
      content: <KpiCardSkeleton />,
    });
  }

  return cells;
}

function buildDashboardCells(options: {
  t: ReturnType<typeof useTranslations<'today'>>;
  dayLabelFormatter: ReturnType<typeof useTodayDayLabelFormatter>;
  widgets: TodaySummaryWidgets;
  charts: TodaySummaryCharts;
  actions: TodaySummaryActions;
  subscription?: TodaySubscriptionSnapshot;
  kpiDefinitions: ReturnType<typeof getVisibleTodayKpis>;
  showSubscriptionCard: boolean;
  showCaseCompletionCard: boolean;
  showUpcoming: boolean;
  showCharts: boolean;
  orgType?: 'CLINIC' | 'LAB';
  isOwner: boolean;
  currentOrganization: ReturnType<typeof useAuth>['currentOrganization'];
}): TodayDashboardCell[] {
  const cells: TodayDashboardCell[] = [];
  const formatDayLabel = (code: string) =>
    formatTodayChartDayLabel(code, options.dayLabelFormatter);

  if (options.showCharts) {
    cells.push(
      ...buildChartCells({
        t: options.t,
        charts: options.charts,
        orgType: options.orgType,
        isOwner: options.isOwner,
        formatDayLabel,
        dayLabelFormatter: options.dayLabelFormatter,
      }),
    );
  }

  if (options.showUpcoming) {
    cells.push({
      id: 'upcoming-appointments',
      layout: TODAY_DASHBOARD_LAYOUT.upcoming,
      content: (
        <TodayUpcomingAppointments actions={options.actions} loading={false} isInitialLoad={false} />
      ),
    });
  }

  if (options.showSubscriptionCard && options.subscription) {
    cells.push({
      id: 'subscription',
      layout: TODAY_DASHBOARD_LAYOUT.subscription,
      content: <TodaySubscriptionKpiCard subscription={options.subscription} />,
    });
  }

  if (options.showCaseCompletionCard && options.charts.caseCompletion !== undefined) {
    const caseCompletion = options.charts.caseCompletion;
    cells.push({
      id: 'case-completion',
      layout: TODAY_DASHBOARD_LAYOUT.subscription,
      content: (
        <TodayCaseCompletionKpiCard
          completed={caseCompletion.completed}
          total={caseCompletion.total}
          percent={caseCompletion.percent}
        />
      ),
    });
  }

  for (const definition of options.kpiDefinitions) {
    const value = definition.formatValue(options.widgets) ?? '—';
    const subtitle = definition.formatSubtitle?.(options.widgets);

    cells.push({
      id: `kpi-${definition.key}`,
      layout: TODAY_DASHBOARD_LAYOUT.kpi,
      content: (
        <KpiCard
          title={options.t(definition.titleKey)}
          value={value}
          subtitle={subtitle}
          icon={definition.icon}
          color={definition.color}
          href={definition.href}
          className="h-full"
        />
      ),
    });
  }

  return cells;
}

function buildChartCells(options: {
  t: ReturnType<typeof useTranslations<'today'>>;
  charts: TodaySummaryCharts;
  orgType?: 'CLINIC' | 'LAB';
  isOwner: boolean;
  formatDayLabel: (code: string) => string;
  dayLabelFormatter: ReturnType<typeof useTodayDayLabelFormatter>;
}): TodayDashboardCell[] {
  const { t, charts, orgType, isOwner } = options;
  const cells: TodayDashboardCell[] = [];
  const tallChart = TODAY_DASHBOARD_LAYOUT.chart;
  const mediumChart = TODAY_DASHBOARD_LAYOUT.chartMedium;

  const appointmentsWeekAllData = mapWeekChartBuckets(
    charts.appointmentsWeekAll ?? [],
    options.dayLabelFormatter,
  );
  const appointmentsWeekMineData = mapWeekChartBuckets(
    charts.appointmentsWeekMine ?? [],
    options.dayLabelFormatter,
  );
  const labTaskActivityData = mapWeekChartBuckets(
    charts.labTaskActivityWeek ?? [],
    options.dayLabelFormatter,
  );

  if (orgType === 'CLINIC' && charts.appointmentsWeekAll !== undefined) {
    cells.push({
      id: 'chart-appointments-week-all',
      layout: tallChart,
      content: (
        <ChartCard
          title={t('chartAppointmentsWeekAllTitle')}
          subtitle={t('chartAppointmentsWeekAllSubtitle')}
          isEmpty={appointmentsWeekAllData.every((row) => row.count === 0)}
          emptyMessage={t('chartEmpty')}
        >
          <TodayAreaChart data={appointmentsWeekAllData} />
        </ChartCard>
      ),
    });
  }

  if (orgType === 'CLINIC' && charts.appointmentsWeekMine !== undefined) {
    cells.push({
      id: 'chart-appointments-week-mine',
      layout: tallChart,
      content: (
        <ChartCard
          title={t('chartAppointmentsWeekMineTitle')}
          subtitle={t('chartAppointmentsWeekMineSubtitle')}
          isEmpty={appointmentsWeekMineData.every((row) => row.count === 0)}
          emptyMessage={t('chartEmpty')}
        >
          <TodayAreaChart data={appointmentsWeekMineData} />
        </ChartCard>
      ),
    });
  }

  if (orgType === 'LAB' && charts.labTaskActivityWeek !== undefined) {
    cells.push({
      id: 'chart-lab-task-activity',
      layout: tallChart,
      content: (
        <ChartCard
          title={t('chartLabTaskActivityTitle')}
          subtitle={t('chartLabTaskActivitySubtitle')}
          isEmpty={labTaskActivityData.every(
            (row) => row.completed === 0 && row.received === 0,
          )}
          emptyMessage={t('chartEmpty')}
        >
          <TodayStackedBarChart
            data={labTaskActivityData}
            completedLabel={t('chartLabTaskCompletedLegend')}
            receivedLabel={t('chartLabTaskReceivedLegend')}
            formatDayLabel={options.formatDayLabel}
          />
        </ChartCard>
      ),
    });
  }

  const prosthesisData = charts.inProgressTasksByProsthesis ?? [];
  if (orgType === 'LAB' && charts.inProgressTasksByProsthesis !== undefined) {
    cells.push({
      id: 'chart-prosthesis-mix',
      layout: tallChart,
      content: (
        <ChartCard
          title={t('chartProsthesisMixTitle')}
          subtitle={t('chartProsthesisMixSubtitle')}
          isEmpty={prosthesisData.length === 0}
          emptyMessage={t('chartEmpty')}
        >
          <TodayDonutChart
            data={prosthesisData}
            labelForCode={(code) =>
              prosthesisData.find((row) => row.code === code)?.label ?? code
            }
            colorForCode={(code, index) => prosthesisTypeColor(code, index)}
            swatchStyleForCode={(code, index) => prosthesisTypeSwatchStyle(code, index)}
            variant="pie"
            sideLegend
          />
        </ChartCard>
      ),
    });
  }

  const efficiencyReportData = charts.efficiencyReport ?? [];
  if (
    isOwner &&
    charts.efficiencyReport !== undefined &&
    efficiencyReportData.length >= 2
  ) {
    cells.push({
      id: 'chart-efficiency-report',
      layout: tallChart,
      content: (
        <ChartCard
          title={t('chartEfficiencyReportTitle')}
          subtitle={
            orgType === 'CLINIC'
              ? t('chartEfficiencyReportSubtitleClinic')
              : t('chartEfficiencyReportSubtitleLab')
          }
          isEmpty={efficiencyReportData.every((row) => row.count === 0)}
          emptyMessage={t('chartEmpty')}
        >
          <TodayDonutChart
            data={efficiencyReportData}
            labelForCode={(code) =>
              efficiencyReportData.find((row) => row.code === code)?.label ?? code
            }
            variant="pie"
            sideLegend
          />
        </ChartCard>
      ),
    });
  }

  const appointmentsByProviderData = charts.appointmentsByProvider ?? [];
  if (orgType === 'CLINIC' && charts.appointmentsByProvider !== undefined) {
    cells.push({
      id: 'chart-appointments-by-provider',
      layout: mediumChart,
      content: (
        <ChartCard
          title={t('chartAppointmentsByProviderTitle')}
          subtitle={t('chartAppointmentsByProviderSubtitle')}
          isEmpty={appointmentsByProviderData.length === 0}
          emptyMessage={t('chartEmpty')}
        >
          <TodayHorizontalBarChart data={appointmentsByProviderData} />
        </ChartCard>
      ),
    });
  }

  const treatmentData = charts.treatmentMixWeek ?? [];
  if (orgType === 'CLINIC' && charts.treatmentMixWeek !== undefined) {
    cells.push({
      id: 'chart-treatment-mix',
      layout: mediumChart,
      content: (
        <ChartCard
          title={t('chartTreatmentMixTitle')}
          subtitle={t('chartTreatmentMixSubtitle')}
          isEmpty={treatmentData.length === 0}
          emptyMessage={t('chartEmpty')}
        >
          <TodayBarChart
            data={treatmentData}
            colorForCode={(code, index) => treatmentTypeColor(code, index)}
          />
        </ChartCard>
      ),
    });
  }

  const tasksData = charts.tasksByWorkflowStep ?? [];
  if (orgType === 'LAB' && charts.tasksByWorkflowStep !== undefined) {
    cells.push({
      id: 'chart-tasks-by-step',
      layout: mediumChart,
      content: (
        <ChartCard
          title={t('chartTasksByStepTitle')}
          subtitle={t('chartTasksByStepSubtitle')}
          isEmpty={tasksData.length === 0}
          emptyMessage={t('chartEmpty')}
        >
          <TodayBarChart data={tasksData} />
        </ChartCard>
      ),
    });
  }

  return cells;
}

function countVisibleCharts(
  charts: TodaySummaryCharts,
  orgType?: 'CLINIC' | 'LAB',
  isOwner = false,
): number {
  let count = 0;
  if (orgType === 'CLINIC') {
    count += charts.appointmentsWeekAll !== undefined ? 1 : 0;
    count += charts.appointmentsWeekMine !== undefined ? 1 : 0;
    count += charts.appointmentsByProvider !== undefined ? 1 : 0;
    count += charts.treatmentMixWeek !== undefined ? 1 : 0;
  }
  if (orgType === 'LAB') {
    count += charts.labTaskActivityWeek !== undefined ? 1 : 0;
    count += charts.inProgressTasksByProsthesis !== undefined ? 1 : 0;
    count += charts.tasksByWorkflowStep !== undefined ? 1 : 0;
  }
  if (
    isOwner &&
    charts.efficiencyReport !== undefined &&
    (charts.efficiencyReport?.length ?? 0) >= 2
  ) {
    count += 1;
  }
  return count;
}
