import { View, Text } from '@react-pdf/renderer';

import { stageLabel } from '@/lib/constants';
import { formatCurrency } from '@/lib/utils/currency';
import { BrandedReportDocument } from './branded-document';
import { makeReportStyles } from './styles';
import type { ReportBranding, DashboardReportConfig } from './types';

/**
 * Data shape consumed by the dashboard report. Caller (the route
 * handler) is responsible for fetching the dashboard service's
 * outputs and packing them into this struct. Keeps the React-PDF
 * tree pure — no DB calls inside the document tree.
 */
export interface DashboardReportData {
  kpis?: {
    totalClients: number;
    activeInterests: number;
    pipelineValue: number;
    pipelineValueCurrency: string;
    occupancyRate: number;
  };
  pipelineCounts?: Array<{ stage: string; count: number }>;
  berthStatus?: {
    available: number;
    underOffer: number;
    maintenance: number;
    sold: number;
    total: number;
  };
  sourceConversion?: Array<{
    source: string;
    total: number;
    won: number;
    lost: number;
    conversionRate: number;
  }>;
  hotDeals?: Array<{
    id: string;
    clientName: string | null;
    mooringNumber: string | null;
    stage: string;
    lastContact: string | null;
  }>;
}

interface DashboardReportProps {
  title: string;
  subtitle?: string;
  branding: ReportBranding;
  generatedAt: string;
  config: DashboardReportConfig;
  data: DashboardReportData;
}

/**
 * Dashboard summary report. The rep picks which widgets to include in
 * `config.widgetIds`; this template renders sections only for widgets
 * present in both the config AND the supplied `data` payload (route
 * handler is responsible for skipping fetches for unselected widgets).
 *
 * Chart-style widgets render as tables here (counts, percentages,
 * cohort breakdowns). The deliberate choice trades a chart's at-a-
 * glance shape for the actual numbers — a printed report is for
 * later reference / sharing, not in-the-moment dashboard scanning,
 * and the table format is fully accessible to screen readers and
 * holds up if the PDF is OCR-scanned downstream.
 */
export function DashboardReport({
  title,
  subtitle,
  branding,
  generatedAt,
  config,
  data,
}: DashboardReportProps) {
  const styles = makeReportStyles(branding);
  const include = (id: string) => config.widgetIds.includes(id);
  const dateRangeLine =
    config.dateFrom || config.dateTo
      ? `${config.dateFrom ?? 'open'} → ${config.dateTo ?? 'today'}`
      : null;

  return (
    <BrandedReportDocument
      branding={branding}
      title={title}
      subtitle={subtitle ?? `Dashboard summary${dateRangeLine ? ` · ${dateRangeLine}` : ''}`}
      generatedAt={generatedAt}
    >
      {include('kpi_overview') && data.kpis ? (
        <View>
          <Text style={styles.sectionTitle}>Key metrics</Text>
          <View style={styles.kpiGrid}>
            <View style={styles.kpiCard}>
              <Text style={styles.kpiLabel}>Total clients</Text>
              <Text style={styles.kpiValue}>{data.kpis.totalClients.toLocaleString()}</Text>
            </View>
            <View style={styles.kpiCard}>
              <Text style={styles.kpiLabel}>Active interests</Text>
              <Text style={styles.kpiValue}>{data.kpis.activeInterests.toLocaleString()}</Text>
            </View>
            <View style={styles.kpiCard}>
              <Text style={styles.kpiLabel}>Pipeline value</Text>
              <Text style={styles.kpiValue}>
                {formatCurrency(String(data.kpis.pipelineValue), data.kpis.pipelineValueCurrency, {
                  maxFractionDigits: 0,
                })}
              </Text>
              <Text style={styles.kpiSubvalue}>Sum of primary-berth prices, active deals only</Text>
            </View>
            <View style={styles.kpiCard}>
              <Text style={styles.kpiLabel}>Occupancy</Text>
              <Text style={styles.kpiValue}>{data.kpis.occupancyRate.toFixed(1)}%</Text>
              <Text style={styles.kpiSubvalue}>Sold berths / total</Text>
            </View>
          </View>
        </View>
      ) : null}

      {include('pipeline_funnel') && data.pipelineCounts ? (
        <View>
          <Text style={styles.sectionTitle}>Pipeline funnel</Text>
          <Text style={styles.sectionSubtitle}>Active interests grouped by pipeline stage.</Text>
          <SimpleTable
            styles={styles}
            headers={['Stage', 'Count']}
            widths={[70, 30]}
            rows={data.pipelineCounts.map((row) => [stageLabel(row.stage), String(row.count)])}
          />
        </View>
      ) : null}

      {include('berth_status') && data.berthStatus ? (
        <View>
          <Text style={styles.sectionTitle}>Berth status</Text>
          <Text style={styles.sectionSubtitle}>Current distribution across the marina.</Text>
          <SimpleTable
            styles={styles}
            headers={['Status', 'Count', '% of total']}
            widths={[50, 25, 25]}
            rows={[
              [
                'Available',
                String(data.berthStatus.available),
                pct(data.berthStatus.available, data.berthStatus.total),
              ],
              [
                'Under offer',
                String(data.berthStatus.underOffer),
                pct(data.berthStatus.underOffer, data.berthStatus.total),
              ],
              [
                'Sold',
                String(data.berthStatus.sold),
                pct(data.berthStatus.sold, data.berthStatus.total),
              ],
              [
                'Maintenance',
                String(data.berthStatus.maintenance),
                pct(data.berthStatus.maintenance, data.berthStatus.total),
              ],
            ]}
          />
        </View>
      ) : null}

      {include('source_conversion') && data.sourceConversion ? (
        <View>
          <Text style={styles.sectionTitle}>Source conversion</Text>
          <Text style={styles.sectionSubtitle}>
            Interest counts grouped by lead source, with win rate per source.
          </Text>
          <SimpleTable
            styles={styles}
            headers={['Source', 'Total', 'Won', 'Lost', 'Win rate']}
            widths={[40, 15, 15, 15, 15]}
            rows={data.sourceConversion.map((row) => [
              row.source,
              String(row.total),
              String(row.won),
              String(row.lost),
              `${(row.conversionRate * 100).toFixed(1)}%`,
            ])}
          />
        </View>
      ) : null}

      {include('hot_deals') && data.hotDeals && data.hotDeals.length > 0 ? (
        <View>
          <Text style={styles.sectionTitle}>Hot deals</Text>
          <Text style={styles.sectionSubtitle}>
            Top active interests, ranked by pipeline stage with most-recent activity as tiebreaker.
          </Text>
          <SimpleTable
            styles={styles}
            headers={['Client', 'Mooring', 'Stage', 'Last contact']}
            widths={[40, 20, 20, 20]}
            rows={data.hotDeals.map((d) => [
              d.clientName ?? '-',
              d.mooringNumber ?? '-',
              stageLabel(d.stage),
              d.lastContact ? new Date(d.lastContact).toLocaleDateString('en-GB') : '-',
            ])}
          />
        </View>
      ) : null}
    </BrandedReportDocument>
  );
}

function pct(n: number, total: number): string {
  return total > 0 ? `${((n / total) * 100).toFixed(1)}%` : '—';
}

interface SimpleTableProps {
  styles: ReturnType<typeof makeReportStyles>;
  headers: string[];
  widths: number[];
  rows: string[][];
}

/**
 * Plain table primitive used by every chart-style widget section.
 * Widths are percentages of the container (sum to 100). Header row is
 * gray; data rows alternate fafafa/white for scannability without the
 * "spreadsheet" feel.
 */
function SimpleTable({ styles, headers, widths, rows }: SimpleTableProps) {
  return (
    <View style={styles.table}>
      <View style={styles.tableHeader}>
        {headers.map((header, i) => (
          <Text key={header + i} style={{ ...styles.tableHeaderCell, width: `${widths[i]}%` }}>
            {header}
          </Text>
        ))}
      </View>
      {rows.map((row, rowIdx) => (
        <View key={rowIdx} style={rowIdx % 2 === 1 ? styles.tableRowZebra : styles.tableRow}>
          {row.map((cell, i) => (
            <Text key={`${rowIdx}-${i}`} style={{ ...styles.tableCell, width: `${widths[i]}%` }}>
              {cell}
            </Text>
          ))}
        </View>
      ))}
    </View>
  );
}
